Arquitectura Profesional
Documento de Arquitectura de Software — Feature-First Atomic Clean Architecture (Flutter 3.5+ / Dart 3.5+)
TeLlevo Pasajero — Documento de Arquitectura de Software
Section titled “TeLlevo Pasajero — Documento de Arquitectura de Software”Plataforma: Flutter 3.5+ / Dart 3.5+ Arquitectura: Feature-First Atomic Clean Architecture Estado: Producción (v6.0.0+69) Códigobase: 494 archivos, 27,120 líneas de Dart, 13 features funcionales
Índice
Section titled “Índice”- Resumen Ejecutivo
- Arquitectura General
- Estructura del Código
- Capas de la Arquitectura
- Patrón Use Case
- Widgets Atómicos
- State Management con Riverpod
- Service Discovery
- Navegación con GoRouter
- Refactorización Masiva
- Métricas de Calidad
- Stack Tecnológico
- Perfil del Desarrollador
1. Resumen Ejecutivo
Section titled “1. Resumen Ejecutivo”TeLlevo Pasajero es una aplicación móvil de ridesharing que conecta suscriptores con colaborador. La aplicación soporta autenticación multi-tenant (individual y empresarial), pagos integrados con Khipu, mapas interactivos con Google Maps, seguimiento de viajes en tiempo real, y notificaciones push con Firebase Cloud Messaging.
Arquitectura en una Frase
Section titled “Arquitectura en una Frase”Feature-First Atomic Clean Architecture: cada feature del negocio es autocontenida con sus propias capas de dominio, datos y presentación, construida mediante widgets atómicos de responsabilidad única.
Métricas Clave
Section titled “Métricas Clave”| Indicador | Valor |
|---|---|
| Archivos totales | 494 |
| Líneas de código | 27,120 |
| Features funcionales | 13 |
| Use cases (lógica de negocio pura) | 59 |
| Widgets reutilizables | 134 |
| Screens | 27 |
| Providers Riverpod | 36 |
| Datasources + Repositories | 69 |
| Archivos < 30 líneas | 193 (39%) |
| Archivos < 100 líneas | 408 (82%) |
| Archivos generados (build_runner) | 37 |
2. Arquitectura General
Section titled “2. Arquitectura General”La arquitectura del proyecto es una evolución pragmática de Clean Architecture adaptada a Flutter, donde cada feature del negocio contiene sus propias capas en lugar de tener capas globales.
Diagrama de Arquitectura General
Section titled “Diagrama de Arquitectura General”graph TB
subgraph "App Layer (lib/)"
direction LR
C[config/]<-->F[features/]
F<-->E[exceptions/]
F<-->U[utils/]
end
subgraph "Feature Layer (lib/features/)"
direction TB
F1[buscar/] --- F2[perfil/] --- F3[login/]
F3 --- F4[viaje/] --- F5[shared/]
F5 --- F6[pago/] --- F7[splash/]
F7 --- F8[welcome/]
end
subgraph "Internal Feature Structure"
direction LR
D[datasources/]-->R[repositories/]
R-->P[providers/]
P-->SC[screens/]
SC-->W[widgets/]
UC[usecases/]-->SC
M[models/]-->MA[mappers/]
MA-->E2[entities/]
end
Flujo de Datos
Section titled “Flujo de Datos”sequenceDiagram
participant Widget
participant Provider
participant UseCase
participant Repository
participant DataSource
participant API
Widget->>Provider: ref.watch(provider)
Provider->>UseCase: validar/transformar
UseCase-->>Provider: resultado
Provider->>Repository: obtener datos
Repository->>DataSource: llamada HTTP
DataSource->>API: request (Dio)
API-->>DataSource: response JSON
DataSource-->>Repository: modelo parseado
Repository-->>Provider: entidad de dominio
Provider-->>Widget: nuevo estado (AsyncValue)
3. Estructura del Código
Section titled “3. Estructura del Código”Árbol de Directorios (Raíz)
Section titled “Árbol de Directorios (Raíz)”lib/├── config/ # Configuración global│ ├── constants/ # Constantes y entorno│ ├── enums/ # Enums globales│ ├── menu/ # Menús│ ├── router/ # GoRouter modular│ └── theme/ # Tema de la app├── exceptions/ # Excepciones personalizadas│ ├── general/│ └── login/├── features/ # 13 features funcionales│ ├── buscar/ # Búsqueda de viajes (84 archivos)│ ├── chat/ # Chat con colaborador│ ├── enums/ # Enums de features│ ├── error/ # Pantallas de error│ ├── fcm/ # Firebase Cloud Messaging│ ├── login/ # Autenticación (54 archivos)│ ├── pago/ # Pagos Khipu (22 archivos)│ ├── perfil/ # Perfil de usuario (91 archivos)│ ├── resumen/ # Resumen de viaje (16 archivos)│ ├── shared/ # Código compartido (61 archivos)│ ├── splash/ # Splash screen (8 archivos)│ ├── viaje/ # Viajes (62 archivos)│ └── welcome/ # Onboarding (9 archivos)├── rest/ # Documentación REST API├── utils/ # Utilidades genéricas└── main.dart # Entry point (99 líneas)Dos Patrones de Estructura Interna
Section titled “Dos Patrones de Estructura Interna”El proyecto usa dos patrones según la complejidad del feature:
Feature con Data Layer (ej: login/)
Section titled “Feature con Data Layer (ej: login/)”lib/features/login/├── data/ # Capa de datos│ ├── datasources/ # 8 archivos (abstract + impl)│ ├── entities/ # 1 entidad│ ├── functions/ # 1 función compartida│ ├── mappers/ # 2 mappers│ └── repositories/ # 8 archivos (abstract + impl)├── presentation/ # Capa de presentación│ ├── providers/ # 11 providers (empresa/, login_respuesta)│ ├── screens/ # 6 screens│ └── widgets/ # 15 widgets atómicos└── usecases/ # 7 use casesFeature Simple (ej: welcome/)
Section titled “Feature Simple (ej: welcome/)”lib/features/welcome/├── screens/ # 1 screen├── usecases/ # 3 use cases└── widgets/ # 5 widgets atómicosCapa Compartida (shared/)
Section titled “Capa Compartida (shared/)”El módulo shared/ contiene todo el código transversal:
- 28 widgets reutilizables (AppBar genérico, avatar, bottom nav, tarjetas, modales)
- 13 use cases compartidos (routing, navegación, validaciones cross-feature)
- 6 providers globales (usuario, estado de aplicación, mapa controller, health status)
- 4 servicios de discovery (config, interceptor, service health monitor)
4. Capas de la Arquitectura
Section titled “4. Capas de la Arquitectura”Diagrama de Capas por Feature
Section titled “Diagrama de Capas por Feature”graph LR
subgraph "Dominio (Domain)"
E[Entities]
UC[Use Cases <br/>59 archivos]
end
subgraph "Datos (Data)"
D[Datasources <br/>35 archivos]
M[Models <br/>15 archivos]
MA[Mappers <br/>13 archivos]
R[Repositories <br/>34 archivos]
end
subgraph "Presentación (UI)"
P[Providers <br/>36 archivos]
SC[Screens <br/>27 archivos]
W[Widgets <br/>134 archivos]
end
E --> MA
MA --> M
D --> R
R --> P
UC --> P
P --> SC
SC --> W
Capa de Dominio
Section titled “Capa de Dominio”Contiene las entidades del negocio y los use cases con lógica pura.
Entidades (22 archivos): Representan objetos de negocio sin dependencias de frameworks.
Coordenada, Prediction, TarifaCO2, Trayectoria, ChatMessage,PerfilPasajero, PreferenciaViajeRequest, Tarjeta, PagoKhipu,Viaje, ViajeActivo, Usuario, UsuarioEmpresa, DeviceToken, ...Use Cases (59 archivos): Clases con un único método execute(), sin dependencias externas. Ver sección 5.
Capa de Datos
Section titled “Capa de Datos”Implementa la comunicación con APIs REST y el mapeo de datos.
Datasources (35 archivos, 18 pares abstract + impl): Definen contratos de comunicación HTTP y sus implementaciones concretas con Dio.
login_datasource.dart (abstract)login_datasource_impl.dart (concreto, Dio)coordenada_datasource.dart (abstract)coordenada_datasource_impl.dart (concreto)Models (15 archivos): Representaciones JSON de las respuestas de API.
Mappers (13 archivos): Transforman Models → Entities y viceversa.
Repositories (34 archivos, 17 pares abstract + impl): Orquestan datasources y aplican lógica de negocio antes de entregar datos a los providers.
Capa de Presentación
Section titled “Capa de Presentación”Construye la interfaz de usuario siguiendo el patrón de widgets atómicos.
Providers (36 archivos): Estado global con Riverpod (ver sección 7).
Screens (27 archivos, <80 líneas): Orquestan widgets y providers. No contienen lógica de negocio ni UI detallada.
Widgets (134 archivos, <100 líneas): Componentes de UI con una única responsabilidad.
5. Patrón Use Case
Section titled “5. Patrón Use Case”Los Use Cases encapsulan lógica de negocio pura (validaciones, formateo, cálculos) fuera de la UI para maximizar la testabilidad y reutilización.
Estructura
Section titled “Estructura”lib/features/{feature}/usecases/├── index.dart # Barrel export├── validar_email_usecase.dart├── formatear_precio_usecase.dart└── ...Ciclo de Vida
Section titled “Ciclo de Vida”flowchart LR
A[UI Event] --> B[Provider/Controller]
B --> C{Use Case}
C -->|Validación| D[Resultado: ok/error]
C -->|Formateo| E[Resultado: string formateado]
C -->|Cálculo| F[Resultado: valor calculado]
D --> B
E --> B
F --> B
B --> G[Nuevo estado]
G --> H[UI Rebuild]
Ejemplo Concreto
Section titled “Ejemplo Concreto”/// Validates complete email formatclass ValidarEmailCompletoUseCase { const ValidarEmailCompletoUseCase();
/// Returns error message or null if valid String? execute(String email) { if (email.isEmpty) { return 'El correo es un campo obligatorio'; } if (!Utils.isValidEmail(email)) { return 'Debe ser un correo válido'; } return null; }}Características:
- 100% pureza funcional (sin efectos secundarios)
- Sin dependencias de Flutter ni Riverpod
- Testable de forma aislada
- 20-60 líneas por use case
Distribución de Use Cases por Feature
Section titled “Distribución de Use Cases por Feature”| Feature | Use Cases | Propósito |
|---|---|---|
| buscar | 10 | Lugares, distancias, tiempos, coordenadas |
| login | 7 | Validación de email, construcción de email, PIN |
| perfil | 12 | Validaciones de formulario (nombre, email, celular, dirección), formato |
| viaje | 8 | Formateo CO2, distancia, direcciones, tabs |
| resumen | 7 | Precios, bounds, polylines, coordenadas |
| pago | 5 | Tipo de pago, mensajes de error, navegación post-pago |
| shared | 13 | Routing, WhatsApp, logging, aplicaciones externas |
| splash | 1 | Inicialización de la app |
| welcome | 3 | Validación de token, preferencias de viaje |
| Total | 59 |
6. Widgets Atómicos
Section titled “6. Widgets Atómicos”El principio fundamental de la UI: un archivo, una responsabilidad, máximo 100 líneas.
Jerarquía de Composición
Section titled “Jerarquía de Composición”graph TB
subgraph "Screen (orquestador)"
S[EditarPerfilScreen<br/>64 líneas]
end
subgraph "Widgets Atómicos"
W1[AppBarGenerico]
W2[ProfileForm<br/>221 líneas]
W3[ProfileLoadingView]
W4[ProfileErrorView]
end
subgraph "Sub-Widgets"
W5[EmailField<br/>42 líneas]
W6[NombreField<br/>43 líneas]
W7[CelularField<br/>49 líneas]
W8[Avatar]
end
S --> W1
S --> W2
S --> W3
S --> W4
W2 --> W5
W2 --> W6
W2 --> W7
W2 --> W8
Patrón de Screen
Section titled “Patrón de Screen”Una Screen nunca contiene UI detallada. Solo orquesta:
class EditarPerfilScreen extends ConsumerWidget { const EditarPerfilScreen({super.key});
@override Widget build(BuildContext context, WidgetRef ref) { final usuario = ref.watch(usuarioProvider); final perfil = ref.watch(perfilPasajeroProvider(usuario.usuarioId)); final estado = ref.watch(estadoAplicacionProvider);
return Scaffold( appBar: AppBarGenerico(title: 'Editar Perfil', ...), body: SafeArea( child: perfil.when( loading: () => const ProfileLoadingView(), error: (error, _) => ProfileErrorView(message: error.toString()), data: (perfilData) => ProfileForm( correoController: TextEditingController(text: perfilData.email), nombreController: TextEditingController(text: perfilData.nombre), ... ), ), ), ); }}Ejemplo de Widget Atómico
Section titled “Ejemplo de Widget Atómico”class ProfileHeader extends StatelessWidget { final String urlIcono; final String nombre; final int cantidadEstrellas;
const ProfileHeader({ super.key, required this.urlIcono, required this.nombre, required this.cantidadEstrellas, });
@override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(left: 12, right: 12), child: Row( children: [ Avatar(urlIconoConductor: urlIcono, size: 50), const SizedBox(width: 15), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(nombre, style: ...), _buildStarRating(), Text('Persona', style: ...), ], ), ), ], ), ); }}85 líneas — Una responsabilidad: mostrar el encabezado del perfil con avatar, nombre y estrellas.
Distribución de Tamaño de Widgets
Section titled “Distribución de Tamaño de Widgets”pie title "Distribución de Archivos Dart (excluyendo generados)"
"≤ 30 líneas" : 193
"31-50 líneas" : 111
"51-80 líneas" : 71
"81-100 líneas" : 33
"> 100 líneas" : 50
El 82% de los archivos tiene ≤ 100 líneas. El 39% tiene ≤ 30 líneas.
7. State Management con Riverpod
Section titled “7. State Management con Riverpod”Riverpod con generación de código (riverpod_annotation + build_runner) es el motor de estado de la aplicación.
Tipos de Providers
Section titled “Tipos de Providers”| Tipo | Uso | Ejemplo |
|---|---|---|
@riverpod | Datos asíncronos (API calls) | perfilPasajeroProvider |
@Riverpod(keepAlive: true) | Estado persistente global | UsuarioNotifier, EstadoAplicacion |
| Providers manuales | Lógica de controller compleja | khipuPaymentController, mapaControllerProvider |
Provider con API Call
Section titled “Provider con API Call”@riverpodFuture<PerfilPasajero> perfilPasajero(Ref ref, int usuarioId) async { final repository = PerfilPasajeroRepositoryImpl( dataSource: PerfilPasajeroDatasourceImpl(), ); try { return await repository.obtenerPerfilPasajero(usuarioId); } on DioException catch (e) { final responseApi = ResponseApi.fromDioException(e); throw InfrastructureException( "Error controlado de la API", responseApi, e, ); }}Provider con Estado Persistente
Section titled “Provider con Estado Persistente”@Riverpod(keepAlive: true)class UsuarioNotifier extends _$UsuarioNotifier { @override UsuarioEmpresa build() { return UsuarioEmpresa(usuarioId: 0, email: ""); }
void setUsuario(UsuarioEmpresa usuario) { state = usuario; }}Manejo de Ciclo de Vida
Section titled “Manejo de Ciclo de Vida”stateDiagram-v2
[*] --> Activo: Widget se monta
Activo --> Disposed: Widget se desmonta (auto-dispose)
Activo --> Activo: ref.watch(otroProvider)
note right of Activo
@riverpod: auto-dispose por defecto
@Riverpod(keepAlive: true): persiste siempre
end note
Archivos Generados
Section titled “Archivos Generados”37 archivos .g.dart generados por build_runner a partir de las anotaciones @riverpod. Esto elimina el boilerplate manual de creación de providers.
8. Service Discovery
Section titled “8. Service Discovery”La aplicación implementa un sistema de Service Discovery dinámico que obtiene las URLs de los microservicios backend desde un Cloudflare Worker, eliminando URLs hardcodeadas.
Arquitectura del Discovery
Section titled “Arquitectura del Discovery”flowchart TB
subgraph "App Startup"
A[App Init] --> B[DiscoveryService.init]
end
subgraph "Cloudflare Worker"
C[Discovery Worker<br/>api.tellevoapp.cl/discovery]
D[(Config<br/>dinámica)]
C --> D
end
subgraph "AppConfig"
E[core: api.tellevoapp.com:7080]
F[pagos: pagos.tellevoapp.com:7081]
G[login: login.tellevoapp.com:7083]
H[htmls: htmls.tellevoapp.com:7082]
end
B -->|GET /discovery| C
C -->|JSON response| B
B -->|parse| E
B -->|parse| F
B -->|parse| G
B -->|parse| H
subgraph "Runtime"
I[Dio Request: /pagos/khipu]
J[DiscoveryInterceptor]
K[URL final: pagos.tellevoapp.com:7081/khipu]
I --> J
J --> K
end
DiscoveryInterceptor
Section titled “DiscoveryInterceptor”Un interceptor de Dio que reescribe las URLs en tiempo real según la configuración obtenida:
class DiscoveryInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { final config = DiscoveryService.config;
if (options.path.startsWith('/pagos')) { options.baseUrl = config.pagos; } else if (options.path.startsWith('/login')) { options.baseUrl = config.login; } else if (options.path.startsWith('/htmls')) { options.baseUrl = config.htmls; } else { options.baseUrl = config.core; } return handler.next(options); }}Flujo de Inicialización
Section titled “Flujo de Inicialización”sequenceDiagram
participant App
participant DiscoveryService
participant Worker as Cloudflare Worker
participant Health as ServiceHealthMonitor
participant Router as GoRouter
App->>DiscoveryService: init()
DiscoveryService->>Worker: GET /discovery
Worker-->>DiscoveryService: {core, pagos, login, htmls}
DiscoveryService-->>App: AppConfig válida
App->>Health: checkAllServices()
Health->>core: healthcheck
Health->>pagos: healthcheck
Health->>login: healthcheck
Health-->>App: All services OK
App->>Router: navegar a /splash
Router->>RouterRedirectHandler: ¿ruta protegida?
Router-->>App: redirigir a splash si no hay health
Manejo de Errores
Section titled “Manejo de Errores”| Escenario | Comportamiento |
|---|---|
| Worker timeout | Splash con botón de reintento |
| Config inválida | DiscoveryException(isRetryable: true) |
| Health check falla | Pantalla ServiceHealthErrorScreen con servicios caídos |
| Sin conexión | Mensaje: “Verifica tu conexión” |
9. Navegación con GoRouter
Section titled “9. Navegación con GoRouter”La navegación usa GoRouter con un diseño modular donde cada feature define sus propias rutas.
Estructura del Router
Section titled “Estructura del Router”lib/config/router/├── app_router.dart # Router principal (61 líneas)├── router_redirect_handler.dart # Protección de rutas (48 líneas)├── routes/│ ├── app_routes.dart # Constantes de ruta│ ├── root_routes.dart # /splash, /error│ ├── main_routes.dart # /welcome, /buscar, /viaje│ ├── login_routes.dart # /seleccion_empresa, /empresa/*│ ├── payment_routes.dart # /khipu, /tarjetaPago│ ├── profile_routes.dart # /perfil, /editar_perfil│ └── info_routes.dart # /acerca_de, /terminos└── index.dart # Barrel fileEsquema de Navegación
Section titled “Esquema de Navegación”graph TB
subgraph "Sin autenticación"
S[/splash]
E[/error]
end
subgraph "Shell Route (Bottom Nav)"
W[/welcome]
B[/buscar]
V[/viaje]
P[/perfil]
end
subgraph "Login Flow"
LE[/seleccion_empresa]
LP[/empresa/:dominio/pin]
LU[/empresaUnirme]
LT[/terminos]
end
subgraph "Sub-rutas"
EP[/editar_perfil]
PV[/preferencia_viaje]
KH[/khipu]
TP[/tarjetaPago]
MP[/medioPago]
AD[/acerca_de]
end
S -->|Discovery OK| W
S -->|Discovery fail| E
E -->|Retry| S
W -->|Login| LE
LE --> LP
LE --> LU
LP --> B
B --> KH
KH --> V
V --> P
P --> EP
P --> PV
P --> AD
P --> TP
P --> MP
Protección de Rutas
Section titled “Protección de Rutas”El RouterRedirectHandler verifica que el servicio de discovery esté operativo antes de permitir el acceso a rutas protegidas:
final handler = RouterRedirectHandler( VerificarRutaProtegidaUseCase(protectedRoutes),);return handler.handleRedirect;17 rutas definidas, de las cuales las rutas principales son protegidas (requieren health check exitoso).
10. Refactorización Masiva
Section titled “10. Refactorización Masiva”En abril de 2025 se realizó una refactorización completa de 18 archivos críticos que transformó monolitos de hasta 622 líneas en 220+ módulos atómicos.
Antes vs Después
Section titled “Antes vs Después”| Archivo Original | Líneas | Archivos Nuevos | Líneas Promedio | Reducción |
|---|---|---|---|---|
componentes.dart | 458 | 5 | 96 | -79% |
preferencia_viaje.dart | 622 | 12 | 52 | -92% |
viaje.dart | 598 | 14 | 43 | -93% |
shell_router.dart | 426 | 14 | 31 | -93% |
formulario.dart | 421 | 12 | 83 | -80% |
editar_perfil.dart | 397 | 14 | 28 | -93% |
mapa.dart | 407 | 14 | 29 | -93% |
khipu.dart | 271 | 8 | 34 | -88% |
welcome.dart | 226 | 7 | 36 | -84% |
splash_screen.dart | 280 | 7 | 34 | -88% |
Estrategia de Migración
Section titled “Estrategia de Migración”flowchart LR
subgraph "Paso 1: Extraer Use Cases"
A[Monolito: 397 líneas] --> B[usecases/<br/>5 archivos<br/>85 líneas total]
end
subgraph "Paso 2: Extraer Widgets"
A --> C[widgets/<br/>10 archivos<br/>340 líneas total]
end
subgraph "Paso 3: Refactorizar Screen"
A --> D[screen.dart<br/>63 líneas<br/>solo orquestación]
end
subgraph "Paso 4: Wrapper Legacy"
A --> E[wrapper.dart<br/>24 líneas<br/>@deprecated + export]
end
B --> D
C --> D
Backward Compatibility
Section titled “Backward Compatibility”Todos los archivos originales se mantienen como wrappers deprecados para no romper imports existentes:
/// DEPRECATED: Use 'editar_perfil_screen.dart' instead@deprecatedexport 'editar_perfil_screen.dart' show EditarPerfilScreen;
@deprecatedtypedef EditarPerfil = EditarPerfilScreen;Esto permite una migración gradual donde el código legacy sigue funcionando mientras se actualizan los imports.
11. Métricas de Calidad
Section titled “11. Métricas de Calidad”Distribución de Archivos por Feature
Section titled “Distribución de Archivos por Feature”| Feature | Archivos | Líneas | % del Códigobase |
|---|---|---|---|
| perfil | 91 | 5,586 | 20.6% |
| buscar | 84 | 3,544 | 13.1% |
| viaje | 62 | 3,827 | 14.1% |
| shared | 61 | 4,585 | 16.9% |
| login | 54 | 3,818 | 14.1% |
| pago | 22 | 1,611 | 5.9% |
| resumen | 16 | 984 | 3.6% |
| config | 23 | 848 | 3.1% |
| splash | 8 | 431 | 1.6% |
| welcome | 9 | 356 | 1.3% |
| error | 2 | 237 | 0.9% |
| utils | 7 | 666 | 2.5% |
| exceptions | 7 | 128 | 0.5% |
| otros | 48 | 499 | 1.8% |
| Total | 494 | 27,120 | 100% |
Distribución por Tipo de Componente
Section titled “Distribución por Tipo de Componente”graph LR
subgraph "Componentes del Códigobase"
UC[Use Cases: 59]
SC[Screens: 27]
WI[Widgets: 134]
PR[Providers: 36]
DS[Datasources: 35]
RE[Repositories: 34]
EN[Entities: 22]
MO[Models: 15]
MA[Mappers: 13]
BA[Barrel Files: 28]
GE[Generated: 37]
end
Distribución de Tamaño de Archivos
Section titled “Distribución de Tamaño de Archivos”| Rango | Archivos | Porcentaje | Acumulado |
|---|---|---|---|
| ≤ 30 líneas | 193 | 39.1% | 39.1% |
| 31-50 líneas | 111 | 22.5% | 61.5% |
| 51-80 líneas | 71 | 14.4% | 75.9% |
| 81-100 líneas | 33 | 6.7% | 82.6% |
| > 100 líneas | 50 | 10.1% | 92.7% |
| Generados (.g.dart) | 36 | 7.3% | 100.0% |
xychart-beta
title "Distribución de Tamaño de Archivos Dart"
x-axis ["≤ 30", "31-50", "51-80", "81-100", "> 100", ".g.dart"]
y-axis "Archivos" 0 --> 200
bar [193, 111, 71, 33, 50, 36]
Conclusiones de las Métricas
Section titled “Conclusiones de las Métricas”-
Responsabilidad Única: El 82% de los archivos tiene ≤ 100 líneas, demostrando adherencia estricta al principio de Single Responsibility.
-
Código Atómico: El 39% de los archivos tiene ≤ 30 líneas — componentes verdaderamente atómicos con una sola función.
-
Balance Feature/Shared: Las features de negocio representan el 90% del código, mientras que
shared/aporta el 17% como capa transversal reutilizable. -
Cobertura de Use Cases: 59 use cases extraen toda la lógica de negocio fuera de la UI, maximizando la testabilidad.
-
Generación de Código: 37 archivos generados (7.3%) eliminan boilerplate y aseguran consistencia en providers.
12. Stack Tecnológico
Section titled “12. Stack Tecnológico”| Tecnología | Versión | Propósito |
|---|---|---|
| Flutter | ^3.5.0 | Framework cross-platform |
| Dart | ^3.5.0 | Lenguaje de programación |
| Android minSdk | 21 | Versión mínima soportada |
| Android targetSdk | 36 | Versión target |
State Management
Section titled “State Management”| Paquete | Versión | Propósito |
|---|---|---|
| flutter_riverpod | ^3.0.3 | State management reactivo |
| hooks_riverpod | ^3.0.3 | State management con hooks |
| riverpod_annotation | ^4.0.0 | Anotaciones para code generation |
| riverpod_generator | ^4.0.0+1 | Generación de providers |
| provider | ^6.0.5 | Legacy (en migración) |
Networking & APIs
Section titled “Networking & APIs”| Paquete | Versión | Propósito |
|---|---|---|
| dio | ^5.7.0 | HTTP client con interceptors |
| http | ^1.0.0 | HTTP client estándar |
| go_router | ^17.0.1 | Navegación declarativa |
Mapas y Geolocalización
Section titled “Mapas y Geolocalización”| Paquete | Versión | Propósito |
|---|---|---|
| google_maps_flutter | ^2.9.0 | Mapas interactivos |
| geolocator | ^14.0.2 | Servicios de ubicación GPS |
| geocoding | ^4.0.0 | Geocoding y reverse geocoding |
| flutter_polyline_points | ^1.0.0 | Políneas de rutas |
| Paquete | Versión | Propósito |
|---|---|---|
| flutter_khipu | ^1.5.3 | SDK de pagos Khipu (Chile) |
Notificaciones
Section titled “Notificaciones”| Paquete | Versión | Propósito |
|---|---|---|
| firebase_core | ^4.4.0 | Firebase core |
| firebase_messaging | ^16.1.1 | Push notifications FCM |
| flutter_local_notifications | ^21.0.0 | Notificaciones locales |
UI y Diseño
Section titled “UI y Diseño”| Paquete | Versión | Propósito |
|---|---|---|
| google_fonts | ^6.3.3 | Tipografía |
| font_awesome_flutter | ^11.0.0 | Iconos |
| flutter_svg | ^2.0.9 | SVG rendering |
| auto_size_text | ^3.0.0 | Texto responsive |
| flutter_html | ^3.0.0-beta.2 | HTML rendering |
Desarrollo
Section titled “Desarrollo”| Paquete | Versión | Propósito |
|---|---|---|
| build_runner | ^2.4.12 | Code generation |
| flutter_lints | ^6.0.0 | Linting |
| riverpod_lint | ^3.0.3 | Riverpod-specific linting |
| custom_lint | ^0.8.1 | Custom lint rules |
13. Perfil del Desarrollador
Section titled “13. Perfil del Desarrollador”Arquitecto y Desarrollador Principal
Section titled “Arquitecto y Desarrollador Principal”Gonzalo Eduardo Oviedo Lambert — Arquitecto de Software Flutter/Dart
Capacidades Demostradas en el Códigobase
Section titled “Capacidades Demostradas en el Códigobase”| Habilidad | Evidencia |
|---|---|
| Clean Architecture | Implementación completa de Feature-First Atomic Clean Architecture con 4 capas por feature |
| State Management Avanzado | Riverpod con generación de código, manejo de ciclo de vida, keepAlive estratégico |
| Refactorización Sistemática | 18 monolitos → 220+ módulos atómicos con backward compatibility |
| Patrones de Diseño | Repository, Interceptor (Dio), Adapter (Mappers), Composition (Widgets), Singleton (DiscoveryService) |
| Arquitectura de Red | Service Discovery dinámico con Cloudflare Workers, interceptors de URL |
| Calidad de Código | 82% de archivos ≤ 100 líneas, 0 errores de análisis estático |
| Navegación Compleja | GoRouter modular con ShellRoute, redirect handler, rutas protegidas |
| Documentación Técnica | Docs por feature, ADRs, diagramas de flujo, guías de troubleshooting |
| Manejo de Errores | Capa de excepciones personalizadas, manejo de DioExceptions, estados de error en UI |
| Testing y CI | flutter analyze, flutter test, build_runner, análisis estático integrado |
| Integración Multi-Servicio | APIs REST, Firebase, Khipu, Google Maps, FCM push notifications |
| Multi-tenencia | Login individual y empresarial con verificación por dominio y PIN |
Enfoque de Desarrollo
Section titled “Enfoque de Desarrollo”Código limpio > Código que funcionaArquitectura > FrameworkTesting > DocumentaciónReutilización > Copiar y pegarMantenibilidad > Velocidad inicialDocumento generado a partir del análisis del códigobase de TeLlevo Pasajero v6.0.0+69 494 archivos Dart, 27,120 líneas, 13 features, 59 use cases, 134 widgets atómicos Refactorización Abril 2025: 18 monolitos → 220+ módulos