Mobile Application Development

Chapter 3
Mobile Software Design and Architecture

Bachelors Program in IT
Mobile Application Development   •   Bachelor

Mobile Software Design and Architecture

Introduction

Mobile applications operate under constraints that distinguish them from many desktop and server systems. A mobile app must respond to changing network conditions, limited battery capacity, constrained memory, variable screen sizes, interruptions from calls and notifications, differing device capabilities, and strict platform lifecycle rules. At the same time, users expect rapid responses, secure handling of personal data, offline continuity, accessibility, and frequent updates.

These demands make architecture more than a matter of arranging source files. Software architecture establishes the major responsibilities of a system, the relationships among those responsibilities, and the rules governing their dependencies. Good architecture allows a development team to change a user interface without rewriting business rules, replace a remote service without redesigning the entire application, and test important behaviour without depending on a physical device or live network.

This chapter examines separation of concerns, modularity, SOLID principles, MVC, MVP, MVVM, the repository pattern, and Clean Architecture. It also compares layered, event-driven, and reactive models and applies these ideas to a mobile application scenario.

Learning Objectives

After studying this chapter, a student should be able to:

  1. Explain why architectural design is important in mobile application development.
  2. Apply separation of concerns and modularity to mobile software.
  3. Use the SOLID principles to evaluate and improve designs.
  4. Compare MVC, MVP, and MVVM in terms of responsibilities, testability, and lifecycle management.
  5. Explain the repository pattern and its relationship to data sources.
  6. Describe the layers and dependency rule of Clean Architecture.
  7. Distinguish layered, event-driven, and reactive architectural models.
  8. Select an appropriate architecture for a mobile application and justify the decision.
  9. Identify architectural risks involving security, privacy, maintainability, performance, and accessibility.

1. Architecture as a Quality Foundation

A software architecture is a set of significant design decisions about the structure and behaviour of a system. It identifies components, interfaces, data flows, dependencies, and constraints. In mobile development, architectural decisions affect at least five major quality attributes:

  • Maintainability: the ease with which defects can be corrected and features changed.
  • Testability: the ability to verify behaviour through automated and manual tests.
  • Scalability of development: the ability of multiple developers or teams to work without excessive conflict.
  • Reliability and resilience: the ability to handle lifecycle changes, network failure, and partial data availability.
  • Performance and resource efficiency: the ability to meet responsiveness, memory, battery, and storage requirements.

Architecture does not guarantee these qualities. It creates conditions that make them achievable. A highly elaborate architecture may be less suitable than a simple one for a small application. Conversely, an initially convenient design may create severe maintenance costs when the application grows.

A useful architectural decision is therefore proportional to the system's risk and expected change. A small calculator may need only a few well-separated components. A banking application may require explicit domain rules, auditability, secure data boundaries, and independent testing of financial operations.

2. Separation of Concerns

Separation of concerns means dividing a system so that each part addresses a distinct responsibility. A user interface should render state and collect user actions; it should not normally contain complex pricing, authentication, or persistence rules. Similarly, a database adapter should not decide how a screen presents an error.

A concern is a behaviour or responsibility that may change independently. Typical mobile concerns include:

  • presentation and navigation;
  • user interaction;
  • domain or business rules;
  • data retrieval and persistence;
  • network communication;
  • local caching;
  • authentication and authorization;
  • logging and monitoring;
  • configuration and feature flags.

Separation is achieved through boundaries and interfaces. For example, a presentation component may depend on an abstraction called TaskRepository rather than directly on a SQL database or HTTP client. The concrete implementation can then be replaced in a test or when the storage technology changes.

Separation of concerns should not be confused with creating a separate class for every line of code. Excessive fragmentation increases navigation overhead and may obscure simple logic. The goal is cohesive components with limited and explicit dependencies.

Cohesion and Coupling

Cohesion describes how closely related the responsibilities within a module are. A module that validates user credentials, formats invoices, and controls animations has low cohesion. A module dedicated to credential validation has higher cohesion.

Coupling describes how strongly modules depend on one another. Directly constructing a network client, database, and navigation controller inside a screen creates high coupling. Passing well-defined interfaces into the screen reduces coupling.

A maintainable design generally seeks high cohesion and low coupling. This is not an absolute rule: tightly coupled components may be justified where performance or platform integration requires it. The design must make the trade-off explicit.

3. Modularity and Dependency Direction

A module is a unit that can be developed, tested, understood, and sometimes deployed independently. In mobile applications, modules may represent features such as Payments, Profile, or Search; technical capabilities such as Networking; or architectural layers such as Domain and Data.

Useful modular boundaries have:

  1. A clear public interface. Other modules should use a small, stable API.
  2. Hidden implementation details. Database schemas and HTTP details should not leak into presentation code.
  3. A single ownership model. It should be clear which module owns a rule or data transformation.
  4. Controlled dependencies. Dependencies should form an understandable graph rather than a circular network.
  5. Independent testability. A module should be testable with fakes or mocks where appropriate.

Dependency direction is especially important. If a screen directly depends on a concrete database class, changes in storage propagate upward. If both screen and database depend on a domain-defined abstraction, the application can replace either implementation more safely.

Dependency injection is a practical technique for controlling dependencies. Instead of a class constructing its collaborators internally, collaborators are supplied from outside. Constructor injection is often preferable because required dependencies are visible and the object cannot be created in an incomplete state.

4. SOLID Principles in Mobile Applications

SOLID is a group of principles for object-oriented design. They are guidelines rather than laws, and they are most useful when applied to change and responsibility rather than mechanically to every class.

Single Responsibility Principle

The Single Responsibility Principle states that a module should have one primary reason to change. A LoginScreen may display login state and forward user actions. Credential encryption, network communication, and token storage should generally be separate responsibilities.

The principle does not mean that every class must contain only one method. It means that unrelated causes of change should not be combined.

Open–Closed Principle

The Open–Closed Principle states that software entities should be open for extension but closed for modification. A payment calculation component might use a PaymentMethod interface so that a new payment method can be added without rewriting stable calculation logic.

This principle should be applied selectively. Creating abstractions for every possible future variation increases complexity. An abstraction is justified when a variation is probable, costly, or already present.

Liskov Substitution Principle

The Liskov Substitution Principle requires that implementations of an abstraction honour the expectations established by that abstraction. If a ReadableCache promises that a missing value returns an empty result, an implementation that unexpectedly throws an exception violates the practical contract.

In mobile systems, this principle is relevant to repositories, storage adapters, and test doubles. A fake repository used in tests should behave sufficiently like the real repository for the behaviour under test.

Interface Segregation Principle

The Interface Segregation Principle recommends several focused interfaces rather than one large interface. A view that only needs to display account information should not depend on methods for deleting users, exporting data, and changing security settings.

Small interfaces reduce accidental coupling and simplify test doubles.

Dependency Inversion Principle

The Dependency Inversion Principle states that high-level policy should not depend directly on low-level implementation details. Both should depend on abstractions. In a mobile application, domain rules should not depend directly on a particular HTTP library or database SDK.

The principle does not eliminate dependencies. It changes their direction so that stable business rules are protected from volatile technical details.

5. Presentation Patterns: MVC, MVP, and MVVM

Presentation patterns organize the relationship among the user interface, user actions, and application state. They are not complete architectures by themselves; a system using MVVM may still require repositories, domain services, and multiple data sources.

Model–View–Controller

In MVC, the Model represents application data and rules, the View presents information, and the Controller interprets input and coordinates actions. On mobile platforms, the practical meaning of MVC varies. A controller such as an activity or view controller can easily become a “massive controller” containing presentation, networking, validation, and navigation logic.

MVC is straightforward for small applications, but its effectiveness depends on keeping the controller thin. Controllers should delegate business operations to suitable components rather than becoming the location of all behaviour.

Model–View–Presenter

In MVP, the View is a relatively passive interface, while the Presenter contains presentation logic. The Presenter receives user actions, requests data, and instructs the View what to display. A view interface can be implemented by a screen, while a test can use a fake view.

MVP often improves unit testability because the Presenter can be tested without a graphical framework. However, lifecycle problems may occur if the Presenter retains a reference to a destroyed screen. The design must handle detachment, cancellation, and recreation carefully.

Model–View–ViewModel

In MVVM, the View observes state exposed by a ViewModel and sends user intents or actions to it. The ViewModel coordinates presentation state while surviving suitable configuration or lifecycle changes. It should not normally hold references to views or platform contexts unless explicitly designed for that purpose.

A ViewModel commonly exposes immutable observable state and accepts events such as Refresh, Submit, or SelectItem. This supports a unidirectional flow:

  1. The View observes state.
  2. The user produces an intent.
  3. The ViewModel processes the intent.
  4. Domain or data components perform work.
  5. New state is emitted.
  6. The View renders the state.

MVVM works particularly well with observable or reactive libraries, but it can be misused. A ViewModel containing database queries, HTTP details, formatting, and business policy becomes a new “massive ViewModel.” The pattern does not remove the need for separation of concerns.

Comparison

PatternMain presentation coordinatorStrengthCommon risk
MVCControllerSimple and familiarMassive controller
MVPPresenterStrong unit-test separationView-reference and lifecycle leaks
MVVMViewModelExplicit state and lifecycle-friendly flowMassive ViewModel or uncontrolled state

The appropriate choice depends on platform conventions, team experience, application complexity, and the chosen state-management approach. Consistency is usually more valuable than selecting a fashionable label.

6. Repository Pattern and Data Boundaries

A repository provides an application-facing interface to data. It coordinates one or more sources, such as a remote service, local database, encrypted preferences, or in-memory cache. The rest of the application asks for meaningful data rather than knowing where that data is stored.

For example, a repository may implement the following policy:

  • return cached product data immediately when available;
  • refresh from a server when the cache is stale;
  • save successful remote results locally;
  • report a meaningful failure when both sources are unavailable.

The repository is not merely a pass-through wrapper around a database. Its value lies in encapsulating data-source selection, synchronization, mapping, caching, and error interpretation.

A useful separation is:

  • Data source: communicates with one technology, such as an API or database.
  • Data model: represents transport or storage structure.
  • Mapper: converts data models into domain models.
  • Repository: applies data-access policy and exposes application-oriented operations.
  • Domain model: represents concepts meaningful to business rules.

Repositories must also define consistency and failure behaviour. Is stale data acceptable? Does a write require confirmation from the server? What happens when the device goes offline during synchronization? These are architectural policies, not merely implementation details.

7. Clean Architecture

Clean Architecture organizes a system into layers and emphasizes the dependency rule: source-code dependencies should point toward policies and abstractions, not toward volatile external details.

A common arrangement contains four conceptual areas:

  1. Entities or domain models: core concepts and rules that are relatively independent of technology.
  2. Use cases or application services: actions the application performs, such as PlaceOrder or LoadCourseSchedule.
  3. Interface adapters: presenters, ViewModels, repository implementations, mappers, and controllers that translate between models.
  4. Frameworks and drivers: user-interface toolkits, databases, operating systems, network libraries, and device services.

The exact number of layers is not sacred. The important idea is that business policy should not be controlled by a database framework or screen lifecycle.

A use case may depend on a repository interface defined near the domain or application layer. A concrete repository in the data layer implements that interface. This is dependency inversion in architectural form.

Clean Architecture offers benefits:

  • business rules can be tested without a device or network;
  • data technologies can change with less impact;
  • external failures can be translated at clear boundaries;
  • teams can reason about responsibilities more easily.

It also has costs. More interfaces, models, and mapping code increase initial development effort. For a very small application, strict layering may become ceremony without meaningful benefit. Architecture should be scaled to risk and expected evolution.

8. Layered, Event-Driven, and Reactive Models

Layered Model

A layered model organizes components into levels, commonly presentation, domain, data, and infrastructure. Each layer offers services to the layer above and hides internal details.

Layering is easy to explain and supports responsibility boundaries. Its weakness is that developers may create rigid pass-through layers or allow violations such as presentation code reaching directly into infrastructure. Layering is a structural model; it does not automatically define how state changes over time.

Event-Driven Model

In an event-driven model, components communicate through events. An event records that something happened, such as PaymentCompleted, LocationUpdated, or SessionExpired. Producers do not necessarily know all consumers.

Event-driven designs can reduce direct coupling and support asynchronous work. They are useful for notifications, analytics, background synchronization, and cross-feature reactions. However, they introduce challenges: event ordering, duplicate delivery, lost events, difficult debugging, and unclear ownership of state. Events should have documented schemas, delivery expectations, and idempotency rules where repeated processing is possible.

Reactive Model

Reactive design treats changing values and asynchronous operations as streams or observable state. Components declare how they respond to changes rather than repeatedly requesting current values. A screen may observe a stream of UI states produced by a ViewModel.

Reactive design can express loading, success, empty, and error states clearly and can coordinate multiple asynchronous sources. It also introduces concerns about cancellation, backpressure, threading, subscription lifetime, and error propagation.

Reactive does not mean “automatically fast,” and event-driven does not mean “always distributed.” They describe interaction and change-propagation models, whereas layered architecture describes structural organization. A mobile application can use all three: layered components, event-driven domain notifications, and reactive presentation state.

CriterionLayeredEvent-drivenReactive
Main focusStructural boundariesOccurrences and messagesChanging values and asynchronous flows
CouplingControlled by layer interfacesReduced through producers and consumersReduced through streams and observers
Main strengthClarity and organizationExtensibility and decoupled reactionsComposable state and async behaviour
Main riskRigid or leaky layersOrdering and delivery complexityLifecycle and cancellation errors
Best useGeneral application structureNotifications and independent reactionsUI state, synchronization, live data

9. Worked Design Example: Campus Transport Application

The following is an illustrative case.

Background

A university wants a mobile application showing campus shuttle locations, schedules, service alerts, and saved routes. Students frequently use the app in areas with weak connectivity. The application must support accessibility, protect location information, and remain usable when the network is unavailable.

Problem

An initial prototype places API calls, JSON parsing, database access, map updates, and button handlers in one screen controller. It works during a demonstration but is difficult to test. Rotation or process recreation loses state, and a slow network request can update a screen that is no longer visible.

Analysis

The prototype violates separation of concerns and has high coupling. It has no explicit policy for stale data, and its location permissions are requested without explaining the purpose to users. A revised architecture should separate presentation state, use cases, repository policy, and platform services.

Approach

The design uses MVVM with a repository and Clean Architecture-inspired boundaries:

  • The View renders immutable screen states: loading, showing routes, empty, or error.
  • The ViewModel accepts intents such as Refresh, SelectRoute, and EnableLocation.
  • Use cases include GetNearbyStops, ObserveServiceAlerts, and SaveRoute.
  • A repository coordinates a remote shuttle API and a local database.
  • A location service abstraction hides platform permission and sensor APIs.
  • Mappers convert API and database records into domain objects.
  • A local cache records retrieval time so the View can identify stale information.

The screen observes state rather than directly observing the database and issuing network calls. A refresh operation is cancellable. If the screen is destroyed, the UI subscription ends while appropriate application-level work may continue or be cancelled according to policy.

Outcome

Unit tests can verify route selection and stale-data policy using fake repositories. Repository tests can verify cache and server coordination. UI tests can verify that each state renders the correct controls. The application remains useful offline and can communicate clearly that data may be outdated.

Learning Points

  1. MVVM organizes presentation but does not replace domain and data boundaries.
  2. A repository is valuable when it contains a genuine data policy.
  3. Lifecycle and cancellation are architectural concerns in mobile software.
  4. Offline behaviour must be designed rather than discovered accidentally.
  5. Privacy and accessibility requirements influence architecture from the beginning.

10. Architecture, Security, Privacy, and Ethics

Architectural boundaries influence security. Authentication tokens should not be scattered through screens, and sensitive data should not be stored in unencrypted files merely because local persistence is convenient. Access control must be enforced by trusted services; hiding a button is not authorization.

Mobile applications should request only necessary permissions, explain their purpose, and provide graceful alternatives when permission is denied. Location, health, financial, educational, and biometric data require particular care. Data minimization reduces both privacy risk and architectural complexity.

Logging requires discipline. Logs should support diagnosis without exposing passwords, tokens, precise locations, or unnecessary personal information. Developers should consider retention, deletion, consent, and applicable privacy law.

Accessibility is also an architectural concern. A design that separates state from presentation makes it easier to provide equivalent content through screen readers, larger text, keyboard or switch input, and suitable colour contrast. Error states should be understandable without relying only on colour or animation.

11. Contemporary Practice and AI-Assisted Development

Current mobile development commonly uses declarative UI frameworks, lifecycle-aware state holders, asynchronous streams, local-first strategies, and modular build systems. These technologies can reinforce good architecture, but they do not replace architectural reasoning.

AI-assisted tools can generate boilerplate, tests, mappings, and documentation. They may also introduce insecure storage, incorrect lifecycle handling, licensing concerns, or code that appears plausible but misunderstands domain rules. Professional practice requires reviewing generated code, validating dependencies, protecting confidential data, and testing edge cases. AI should support design decisions, not become an unexamined source of architecture.

12. Best Practices and Common Failure Modes

Effective mobile architecture commonly follows these practices:

  • define responsibilities before selecting patterns;
  • keep business rules independent of UI and infrastructure;
  • expose small, meaningful interfaces;
  • inject dependencies rather than constructing them throughout the application;
  • model loading, success, empty, and failure states explicitly;
  • make asynchronous work cancellable and lifecycle-aware;
  • provide deterministic fakes for unit tests;
  • document caching, synchronization, and error policies;
  • measure performance rather than assuming that abstraction is free;
  • review architecture as requirements and team size change.

Common failure modes include choosing MVVM without defining state ownership, creating repositories that merely forward every database method, adding layers that contain no meaningful responsibility, allowing event buses to become invisible global control flow, and using reactive streams without understanding subscription lifetime. Another failure is treating architecture as permanent. Good architecture evolves through measured refactoring.

Chapter Summary

Mobile software architecture structures responsibilities and dependencies so that applications can remain understandable, testable, secure, and adaptable under device and network constraints. Separation of concerns divides presentation, domain, data, and infrastructure responsibilities. Modularity supports independent development and controlled dependencies; high cohesion and low coupling are useful design goals.

SOLID principles provide guidance for responsibility, extension, substitution, interfaces, and dependency direction. MVC, MVP, and MVVM are presentation patterns rather than complete architectures. MVVM is particularly suitable for explicit, lifecycle-aware state, but it can still become overloaded. The repository pattern hides data-source decisions and supports caching, synchronization, and offline policies.

Clean Architecture places stable domain and application policies inside boundaries protected from frameworks and infrastructure. Layered, event-driven, and reactive models address different aspects of design and can be combined. Architectural decisions must also address privacy, security, accessibility, performance, lifecycle, and ethical use of data. The best architecture is not the most elaborate one; it is the simplest structure that manages the system’s current risks and likely changes.

Key Terms

Separation of concerns: Dividing software into parts with distinct responsibilities.

Modularity: Organizing software into relatively independent units with defined interfaces.

Cohesion: The degree to which responsibilities within a module belong together.

Coupling: The degree of dependency between modules.

Dependency injection: Supplying an object’s collaborators from outside rather than constructing them internally.

SOLID: Five principles for maintainable object-oriented design.

MVC: Model–View–Controller presentation pattern.

MVP: Model–View–Presenter presentation pattern.

MVVM: Model–View–ViewModel presentation pattern based on state and user intents.

Repository: An application-facing abstraction that coordinates data sources and data-access policy.

Data source: A component communicating with a specific storage or external service.

Use case: An application operation expressing a meaningful user or business action.

Clean Architecture: An architectural approach that protects inner policies from external implementation details.

Layered architecture: A structure that organizes responsibilities into conceptual levels.

Event-driven architecture: A model in which components communicate through events.

Reactive architecture: A model based on propagation of changing values and asynchronous streams.

Lifecycle: The states and transitions through which a mobile component or process passes.

Idempotency: The property that repeated processing produces the same intended result as one processing operation.

Technical debt: Future cost created by expedient design or implementation choices.

Review Questions

Short Answer Questions

  1. What is meant by separation of concerns in a mobile application?
  2. Distinguish cohesion from coupling.
  3. State the main purpose of a repository.
  4. What is the dependency rule in Clean Architecture?
  5. Identify one major risk associated with reactive programming on mobile devices.

Long Answer Questions

  1. Explain the five SOLID principles and illustrate at least three with mobile application examples.
  2. Compare MVC, MVP, and MVVM with reference to testability, lifecycle management, and state handling.
  3. Describe how a repository can coordinate a remote API, local cache, and offline behaviour.
  4. Explain the layers of Clean Architecture and discuss its benefits and costs.
  5. Compare layered, event-driven, and reactive models. Explain how they may be combined in one application.

Analytical / Application Questions

  1. A mobile banking screen directly performs validation, database writes, and API calls. Diagnose the architectural problems and propose a revised design.
  2. Design the architecture of an offline-first library application. Specify presentation pattern, use cases, repository policy, and behaviour when cached data is stale.
  3. A team proposes a global event bus for all communication between features. Evaluate the proposal and recommend conditions under which events should or should not be used.

Multiple Choice Questions with Answers

Question 1

Which design goal is most directly supported by separation of concerns?

A. Combining all behaviour in one controller

B. Allowing responsibilities to change independently

C. Removing all interfaces from a system

D. Storing every object in a global variable

Correct Answer: B. Allowing responsibilities to change independently

Question 2

Which SOLID principle says that high-level policy should not depend directly on low-level implementation details?

A. Single Responsibility Principle

B. Open–Closed Principle

C. Interface Segregation Principle

D. Dependency Inversion Principle

Correct Answer: D. Dependency Inversion Principle

Question 3

What is a common responsibility of a ViewModel in MVVM?

A. Rendering every pixel directly

B. Exposing presentation state and processing user intents

C. Owning the database schema

D. Replacing the operating system lifecycle

Correct Answer: B. Exposing presentation state and processing user intents

Question 4

Which statement best describes a repository?

A. A class that must always be a database wrapper with no policy

B. An abstraction that coordinates data sources and data-access policy

C. A user-interface widget for displaying lists

D. A network protocol used by all mobile applications

Correct Answer: B. An abstraction that coordinates data sources and data-access policy

Question 5

In Clean Architecture, which dependency direction is preferred?

A. Domain policy depends directly on a specific database SDK

B. Screens depend directly on every infrastructure component

C. External implementation details depend on stable inner abstractions

D. All layers depend on one global controller

Correct Answer: C. External implementation details depend on stable inner abstractions

Question 6

Which model primarily organizes components into structural levels such as presentation, domain, and data?

A. Layered model

B. Event-driven model

C. Reactive model

D. Peer-to-peer model

Correct Answer: A. Layered model

Question 7

A message such as PaymentCompleted is most characteristic of which architectural model?

A. Event-driven

B. Layered only

C. Procedural only

D. Batch-only

Correct Answer: A. Event-driven

Question 8

Which is a significant risk of event-driven mobile design?

A. It makes all components compile into one function

B. It eliminates the need for data models

C. Event ordering and duplicate delivery may be difficult to manage

D. It prevents asynchronous processing

Correct Answer: C. Event ordering and duplicate delivery may be difficult to manage

Question 9

Why should a mobile application make asynchronous work lifecycle-aware?

A. To ensure obsolete screens are not updated after destruction

B. To guarantee that every request completes successfully

C. To eliminate the need for error handling

D. To prevent all background processing

Correct Answer: A. To ensure obsolete screens are not updated after destruction

Question 10

Which practice best supports privacy by design?

A. Requesting every available device permission at startup

B. Logging authentication tokens for troubleshooting

C. Collecting and retaining only data necessary for the application purpose

D. Relying on hidden buttons as the only access control

Correct Answer: C. Collecting and retaining only data necessary for the application purpose

Mobile Application Development
Chapter 3 of 15