El código de Flutter que me niego a escribir más (y mis alternativas más limpias)

Harsh Mittal

Harsh Mittal.13 de julio de 2025. MEDIUM

Siendo sincero, mi código inicial de Flutter era un desastre .
Hice lo que la mayoría: lo escribí todo yo mismo, intenté controlarlo todo y terminé manteniendo un código espagueti. 🙈

Pero con el tiempo (y mucha refactorización), comencé a tratar mi código base de Flutter como un producto: modular, legible y optimizado para la cordura.

A continuación, un vistazo al código que ya no escribo , lo que uso en su lugar y por qué hice el cambio (con lecciones aprendidas con esfuerzo).

1️⃣ ❌ Conexión manual de varios campos de texto OTP

✅ Cambiado a:pinput

campo_de_texto_de_entrada_pin | Paquete Flutter

Un widget de campo de texto que ayuda a mostrar diferentes estilos de pin escritos en Dart puro, sin dependencias adicionales.

pub.dev

Entonces (Yo vs 50 líneas de texto repetitivo):

Fila ( 
hijos : Lista.generar ( 6 , (índice) { devolver Expandido ( hijo : CampoDeTexto ( controlador : controladores[índice], NodoDeFoco : NodosDeFoco[índice], LongitudMáxima : 1 , ), ); }), ) ;







😵 Concéntrate en saltar pesadillas, sin animación incorporada, sin estilos de error, solo un gran bloque de dolor manual.

Ahora (1 línea de felicidad):

Pinput ( 
longitud : 6 ,
onCompleted : (pin) => imprimir (pin),
)

💡Por qué me cambié : se ve mejor, se siente mejor, maneja casos extremos y me permite concentrarme en la lógica empresarial, no en reinventar el teclado.

2️⃣ ❌ Creación manual de formularios conTextEditingController

✅ Cambiado a:flutter_form_builder

flutter_form_builder | Paquete Flutter

Este paquete ayuda en la creación de formularios en Flutter eliminando el código repetitivo, reutilizando la validación y reaccionando…

pub.dev

En el pasado, mi lógica de formulario se veía así:

final_emailController = TextEditingController ();
TextFormField( 
controlador: _emailController,
validador: (valor) {
si (!valor!.contiene('@')) devuelve 'Correo electrónico no válido';
devuelve nulo;
},
)

¿Problemas?

  • El infierno del controlador
  • Validación manual
  • Pesadilla a escala

Ahora:

FormBuilderTextField ( 
nombre : 'email' ,
validador : FormBuilderValidators.email ( ),
)

💡Por qué me cambié : validadores integrados, sin código repetitivo de controlador y mucho más fácil de escalar para formularios grandes.

3️⃣ ❌ setState()En todas partes

✅ Cambiado a: Provider+ ViewModels estilo MVVM

Cuando no me importaba la arquitectura, esto era común:

TextField ( 
onChanged : (valor) {
setState (() {
nombre = valor;
});
},
)

🛑 Problemas:

  • Lógica pegada a la interfaz de usuario
  • No se puede reutilizar ni probar
  • Se siente sucio en aplicaciones grandes.

Ahora:

clase  UserViewModel  extiende  ChangeNotifier { 
String nombre = '' ;
void updateName ( String newName ) {
nombre = newName;
notifyListeners ();
}
}

En la interfaz de usuario:

Campo de texto ( 
onChanged: context.read<UserViewModel>() .updateName ,
)

💡 Por qué me cambié : Este patrón escala. Puedes probar el ViewModel, reutilizarlo y mantener tus widgets simples (como deberían ser).

4️⃣ ❌ Análisis manual de JSON

✅ Cambiado a:json_serializable

Si tuviera un dólar por cada vez que escribí esto:

fábrica Usuario . fromJson ( Map < String , dynamic> json ) { 
return Usuario (
nombre : json[ 'nombre' ],
edad : json[ 'edad' ],
);
}

😤 Repetitivo, frágil y propenso a errores a medida que tus modelos crecen.

Ahora:

@JsonSerializable() 
clase Usuario {
final String nombre;
final int edad;
  fábrica User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); 
Map<String, dynamic> toJson() => _$UserToJson(this);
}

💡 Por qué me cambié : Confío más en la generación de código que en mi velocidad de escritura. Además, es más limpio y está preparado para el futuro.

5️⃣ ❌ Uso MediaQuerypara cualquier diseño adaptable

✅ Cambiado a: LayoutBuildercon puntos de interrupción

Antes hice:

si (MediaQuery.of(contexto).size.width < 600 ) { 
devolver Columna(...);
} de lo contrario {
devolver Fila(...);
}

Funcionó. Hasta que dejó de funcionar.

😓 Los diseños se rompieron, la lógica se dispersó y los ajustes de respuesta se convirtieron en un desastre.

Ahora:

LayoutBuilder ( 
constructor: (contexto, restricciones) {
devolver restricciones .maxWidth < 600
? MobileLayout ()
: DesktopLayout ();
},
)

💡 Por qué me mudé : Un solo lugar para la lógica del diseño. Mucho más fácil de gestionar en pantallas más grandes.

6️⃣ ❌ Llamar a las API directamente dentro de los widgets

✅ Cambiado a: Capa de servicio API + ViewModel

Sí, solía hacer esto:

FutureBuilder ( 
futuro : http.get ( Uri.parse ( ' https://api.com/data' )),
constructor : (contexto, instantánea) => ...
);

⛔ La interfaz de usuario se integró con la lógica de la API. No se pudo reutilizar. No se pudo reintentar. No se pudo separar.

Ahora:

clase  ApiService  {
Future< Lista <Elemento>> fetchItems() async {respuesta
final = await http.get( Uri.parse ( 'URL de la API' ) ); return parseItems(response.body); }} clase ItemsViewModel extiende ChangeNotifier { ApiService final _apiService; Lista <Elemento> elementos = []; Future< void > loadItems() async { elementos = await _apiService.fetchItems(); notifyListeners(); }}











💡Por qué me cambié : Mejor arquitectura, interfaz de usuario más limpia, más control sobre estados de error, reintentos y almacenamiento en caché.

🚀 Palabras finales: El código que no escribes importa

A medida que maduré como desarrollador, aprendí esto:

No te pagan por escribir código. Te pagan por resolver problemas. Cuanto menos código, mejor, si logras más.

Ya no busco código ingenioso. Busco código limpio.
Reutilizable. Mantenible. Probable. ¿Y, sinceramente? Simplemente menos agotador.

💬 Tu turno

¿Cuál fue el peor código de Flutter que solías escribir pero que luego descartaste?

Déjalo en los comentarios: ayudemos al próximo desarrollador a evitar el dolor. 😅

🔗 Mantengámonos en contacto

Comparto prácticas reales de Flutter, patrones de arquitectura, configuraciones REST/Firebase y cómo administro aplicaciones de clientes reales, no solo tutoriales.

Comparte en tus perfiles

Facebook
Twitter
LinkedIn

Artículos Relacionados:

Las Claves del Sector del Agua

Alejandro Maceira, 3 de noviembre de 2025. iAGUA La nueva Directiva sobre el Tratamiento de Aguas Residuales Urbanas marca un punto de inflexión para el sector del agua en España. Su trasposición exigirá actuar con visión de sistema: integrar gobernanza, financiación, innovación tecnológica y participación ciudadana en un marco que combina urgencia y oportunidad. La

Seguir leyendo »

El asunto del clima: «clima», «klima», humanos y biosfera

Por  Antonio Pou. Noviembre 3, 2025. El Nacional Ambiente: situación y retos. El klima Cuando hace más de dos mil años los sabios griegos hablaban de κλίμα (“klima”), se referían a la diferente inclinación que tenían los rayos solares en distintos territorios a medio día en el momento de los equinoccios (uno hacia el 20

Seguir leyendo »

¿Cuáles deberían ser las prioridades de la agricultura europea?

Roberto Garcia Torrente. 28 octubre 2025. Fundación Cajamar La autonomía estratégica de la Unión Europea: un reto más allá de la defensa y la energía Durante los últimos años se ha ido instalando en la Unión Europea la idea de que es necesario asegurar la autonomía estratégica en una serie de ámbitos clave como son la sanidad,

Seguir leyendo »