Guia PES

App mòbil

Triar la tecnologia i muntar una arquitectura que aguanti tres sprints

Cap tecnologia és obligatòria. El que compta és que la decisió estigui justificada i que el codi sigui net, provat i fàcil de canviar quan el backend o el servei de l'altre equip canviïn.

Les opcions

Natiu

Android

Kotlin + Jetpack Compose, l'opció oficial. Java o Kotlin amb Views és el món antic: el trobareu en codi heretat.

Natiu

iOS

Swift + SwiftUI. UIKit és l'opció antiga. Cal un Mac per compilar i per publicar.

Multiplataforma

Flutter

Dart i un sol codi per a Android, iOS, web i escriptori. Molts paquets a pub.dev i bona integració amb Firebase o Supabase.

Multiplataforma web

React Native

JavaScript o TypeScript amb React. Ionic i Cordova són alternatives més basades en web.

Natiu compartit

Kotlin Multiplatform

La lògica en Kotlin compartida entre Android i iOS. Amb Compose Multiplatform també compartiu la UI.

Com triar

Preguntes clau

  • Què sap ja l'equip?
  • Necessiteu iOS i teniu Mac?
  • Hi ha llibreries per al que voleu (mapes, login social, xat)?
  • Ho justifiqueu a la memòria?

El mateix model en tres llenguatges

data class Station(val id: Int, val name: String, val freeBikes: Int)

// null safety: si no hi ha estació, un text per defecte
fun label(s: Station?) = s?.name ?: "Desconeguda"

Dues arquitectures que separen la UI de la lògica

La regla és la mateixa: la vista no parla mai directament amb l'API. Així podeu provar la lògica sense pantalles i canviar la font de dades (mock o real) sense tocar la UI.

MVVM (Android, iOS)

View
binder
ViewModel
crida
Model

El binder és l'enllaç reactiu: StateFlow, LiveData, Combine. La vista observa l'estat i es redibuixa sola (patró Observer).

BLoC (Flutter)

UI
events / states
BLoC
petició
Data

Els events entren (un toc, l'obertura de la pantalla), el BLoC els processa i emet states que la UI pinta.

class StationsViewModel(private val source: StationsDataSource) : ViewModel() {
    private val _stations = MutableStateFlow<List<Station>>(emptyList())
    val stations: StateFlow<List<Station>> = _stations

    init {
        viewModelScope.launch { _stations.value = source.getStations().sortedBy { it.name } }
    }
}

@Composable
fun StationsScreen(vm: StationsViewModel = koinViewModel()) {
    val stations by vm.stations.collectAsStateWithLifecycle()
    LazyColumn {
        items(stations) { StationRow(it) }
    }
}

Per a projectes més grans, el paquet flutter_bloc fa explícits els events i els states. Per començar, un ValueNotifier ja separa la lògica de la UI.

Linters: codi a punt per ensenyar

Un linter analitza el codi sense executar-lo i troba errors i problemes d'estil. L'objectiu és un codi net, com un document que algú altre haurà de llegir. Compta per a la gestió de la qualitat.

  • Kotlin: ktlint (estil) i detekt (problemes de codi).
  • Swift: SwiftLint.
  • Dart: flutter analyze amb el paquet flutter_lints, i dart format.
  • JavaScript o TypeScript: ESLint i Prettier.
  • Tot plegat: SonarQube o SonarCloud per seguir-ho al llarg del curs.

Un test que el mock fa possible

test('ordena les estacions per nom', () async {
  final bloc = StationsBloc(FakeStationsDataSource());
  await bloc.load();
  final names = bloc.stations.value.map((s) => s.name).toList();
  expect(names, [...names]..sort());
});

Sense xarxa i en mil·lisegons. Genereu la font de dades falsa al generador i afegiu la cobertura a la memòria (flutter test --coverage, Kover o JaCoCo a Kotlin).

Integració contínua amb GitHub Actions

Cada pull request passa el linter, els tests i el build abans de fusionar-se. És la gestió de configuracions que s'avalua. Deseu el fitxer a .github/workflows/ci.yml. Alternatives: GitLab CI, Jenkins, Codemagic o Azure DevOps.

name: Android CI
on:
  pull_request:
  push:
    branches: [develop, main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: '17'
      - name: Lint, tests i build
        run: |
          chmod +x gradlew
          ./gradlew lint testDebugUnitTest assembleDebug
      # amb els plugins de ktlint i detekt: ./gradlew ktlintCheck detekt

Fer arribar l'app a professors i stakeholders

Privada · gratuïta

Firebase App Distribution

Envieu cada versió per correu a qui la vulgueu provar, Android i iOS. La manera més còmoda per a PES.

Privada

TestFlight

Per a iOS. Cal el programa de desenvolupadors d'Apple.

Botigues

Google Play i App Store

La pista de proves interna de Google Play és una bona primera passa. També hi ha botigues alternatives com F-Droid.

Per a l'entrega final, la informació de la release ha d'explicar pas a pas com executar l'app. Un APK a GitHub Releases més un enllaç de distribució ho posa molt fàcil. Vegeu el Fag-5 →

Assistents d'IA: sí, però amb ulls

Gemini, Copilot, Claude i similars ajuden a planificar i dissenyar (esborranys d'arquitectura), a generar codi repetitiu, a depurar (explicar errors, refactoritzar) i a automatitzar fluxos amb agents.

Exemples i recursos

Dues implementacions de la mateixa app d'estacions de Bicing, mostrades en directe a la sessió de desenvolupament mòbil del curs. Fixeu-vos com separen UI, lògica i dades.