Dart efectivo
Mejores prácticas para construir bibliotecas Dart consistentes, mantenibles y eficientes.
En los últimos años, hemos escrito una gran cantidad de código Dart y aprendido mucho sobre qué funciona bien y qué no. Compartimos esto contigo para que también puedas escribir código consistente, robusto y rápido. Hay dos temas principales:
-
Sé consistente. Cuando se trata de cosas como el formato y el uso de mayúsculas, los argumentos sobre cuál es mejor son subjetivos e imposibles de resolver. Lo que sí sabemos es que ser consistente es objetivamente útil.
Si dos fragmentos de código se ven diferentes, debería ser porque son diferentes de alguna manera significativa. Cuando un fragmento de código resalta y llama tu atención, debería hacerlo por una razón útil.
-
Sé breve. Dart fue diseñado para ser familiar, por lo que hereda muchas de las mismas declaraciones y expresiones que C, Java, JavaScript y otros lenguajes. Pero creamos Dart porque hay mucho espacio para mejorar lo que esos lenguajes ofrecen. Agregamos un montón de características, desde la interpolación de cadenas hasta los parámetros de inicialización, para ayudarte a expresar tu intención de manera más simple y fácil.
Si hay múltiples formas de decir algo, generalmente deberías elegir la más concisa. Esto no significa que debas hacer code golf para meter un programa entero en una sola línea. El objetivo es código que sea económico, no denso.
Las guías
#Dividimos las pautas en algunas páginas separadas para facilitar su lectura:
-
Guía de estilo – Esto define las reglas para el diseño y organización del código, o al menos las partes que
dart formatno maneja por ti. La guía de estilo también especifica cómo se formatean los identificadores:camelCase,using_underscores, etc. -
Guía de documentación – Esto te dice todo lo que necesitas saber sobre qué va dentro de los comentarios. Tanto los comentarios de documentación como los comentarios de código normales y corrientes.
-
Guía de uso – Esto te enseña cómo hacer el mejor uso de las características del lenguaje para implementar comportamiento. Si está en una declaración o expresión, está cubierto aquí.
-
Guía de diseño – Esta es la guía más suave, pero la que tiene el alcance más amplio. Cubre lo que hemos aprendido sobre diseñar APIs consistentes y utilizables para bibliotecas. Si está en una firma de tipo o declaración, esto lo cubre.
Para enlaces a todas las pautas, consulta el resumen.
Cómo leer las guías
#Cada guía se divide en algunas secciones. Las secciones contienen una lista de pautas. Cada pauta comienza con una de estas palabras:
-
Las pautas DO describen prácticas que siempre deben seguirse. Casi nunca habrá una razón válida para desviarse de ellas.
-
Las pautas DON'T son lo contrario: cosas que casi nunca son una buena idea. Con suerte, no tenemos tantas como otros lenguajes porque tenemos menos bagaje histórico.
-
Las pautas PREFER son prácticas que deberías seguir. Sin embargo, puede haber circunstancias donde tenga sentido hacer lo contrario. Solo asegúrate de entender las implicaciones completas de ignorar la pauta cuando lo hagas.
-
Las pautas AVOID son el dual de "preferir": cosas que no deberías hacer pero donde puede haber buenas razones para hacerlo en raras ocasiones.
-
Las pautas CONSIDER son prácticas que puedes o no querer seguir, dependiendo de las circunstancias, precedentes y tu propia preferencia.
Algunas pautas describen una excepción donde la regla no aplica. Cuando se listan, las excepciones pueden no ser exhaustivas—es posible que aún necesites usar tu juicio en otros casos.
Esto suena como si la policía fuera a derribar tu puerta si no tienes los cordones atados correctamente. Las cosas no son tan malas. La mayoría de las pautas aquí son sentido común y somos personas razonables. El objetivo, como siempre, es código agradable, legible y mantenible.
El analizador de Dart proporciona un linter para ayudarte a escribir código bueno y consistente que siga estas y otras pautas. Si existe una o más reglas de linter que pueden ayudarte a seguir una pauta entonces la pauta enlaza a esas reglas. Los enlaces usan el siguiente formato:
Regla de linter: unnecessary_getters_setters
Para aprender a usar el linter, consulta Habilitar reglas de linter y la lista de reglas de linter.
Glosario
#Para mantener las pautas breves, usamos algunos términos abreviados para referirnos a diferentes construcciones de Dart.
-
Un miembro de biblioteca es un campo, getter, setter o función de nivel superior. Básicamente, cualquier cosa en el nivel superior que no sea un tipo.
-
Un miembro de clase es un constructor, campo, getter, setter, función u operador declarado dentro de una clase. Los miembros de clase pueden ser de instancia o estáticos, abstractos o concretos.
Un miembro es un miembro de biblioteca o un miembro de clase.
-
Una variable, cuando se usa generalmente, se refiere a variables de nivel superior, parámetros y variables locales. No incluye campos estáticos o de instancia.
Un tipo es cualquier declaración de tipo con nombre: una clase, typedef o enum.
-
Una propiedad es una variable de nivel superior, getter (dentro de una clase o en el nivel superior, de instancia o estático), setter (igual), o campo (de instancia o estático). Aproximadamente cualquier construcción con nombre "similar a un campo".
Resumen de todas las reglas
#Estilo
#Identifiers
-
DO nombra los tipos usando
UpperCamelCase. -
DO nombra las extensiones usando
UpperCamelCase. -
DO nombra paquetes, directorios y archivos fuente usando
lowercase_with_underscores. -
DO nombra los prefijos de importación usando
lowercase_with_underscores. -
DO nombra otros identificadores usando
lowerCamelCase. -
PREFER usar
lowerCamelCasepara nombres de constantes. - DO escribe con mayúsculas los acrónimos y abreviaturas de más de dos letras como palabras.
- PREFER usar comodines para parámetros de callback no utilizados.
- DON'T uses un guion bajo al principio para identificadores que no son privados.
- DON'T uses letras de prefijo.
- DON'T nombres explícitamente las bibliotecas.
Ordering
-
DO coloca las importaciones
dart:antes de otras importaciones. -
DO coloca las importaciones
package:antes de las importaciones relativas. - DO especifica las exportaciones en una sección separada después de todas las importaciones.
- DO ordena las secciones alfabéticamente.
Formatting
Documentación
#Comments
Doc comments
-
DO usa comentarios de documentación
///para documentar miembros y tipos. - PREFER escribir comentarios de documentación para APIs públicas.
- CONSIDERA escribir un comentario de documentación a nivel de biblioteca.
- CONSIDERA escribir comentarios de documentación para APIs privadas.
- DO comienza los comentarios de documentación con un resumen de una sola oración.
- DO separa la primera oración de un comentario de documentación en su propio párrafo.
- EVITA la redundancia con el contexto circundante.
- PREFER comenzar los comentarios de una función o método con verbos en tercera persona si su propósito principal es un efecto secundario.
- PREFER comenzar un comentario de variable o propiedad no booleana con una frase nominal.
- PREFER comenzar un comentario de variable o propiedad booleana con "Si" seguido de una frase nominal o gerundio.
- PREFER una frase nominal o frase verbal no imperativa para una función o método si devolver un valor es su propósito principal.
- DON'T escribas documentación tanto para el getter como para el setter de una propiedad.
- PREFER comenzar los comentarios de biblioteca o tipo con frases nominales.
- CONSIDERA incluir ejemplos de código en los comentarios de documentación.
- DO usa corchetes en los comentarios de documentación para referirse a identificadores en alcance.
- DO usa prosa para explicar parámetros, valores de retorno y excepciones.
- DO coloca los comentarios de documentación antes de las anotaciones de metadatos.
Markdown
- EVITA usar markdown excesivamente.
- EVITA usar HTML para formato.
- PREFER cercas de comillas invertidas para bloques de código.
Writing
Uso
#Libraries
-
DO usa cadenas en directivas
part of. -
DON'T importes bibliotecas que están dentro del directorio
srcde otro paquete. -
DON'T permitas que una ruta de importación entre o salga de
lib. - PREFER rutas de importación relativas.
Null
-
DON'T inicialices explícitamente variables a
null. -
DON'T uses un valor predeterminado explícito de
null. -
DON'T uses
trueofalseen operaciones de igualdad. -
EVITA variables
latesi necesitas verificar si están inicializadas. - CONSIDERA la promoción de tipos o patrones de verificación de nulos para usar tipos anulables.
Strings
- DO usa cadenas adyacentes para concatenar literales de cadena.
- PREFER usar interpolación para componer cadenas y valores.
- EVITA usar llaves en la interpolación cuando no sea necesario.
Collections
- DO usa literales de colección cuando sea posible.
-
DON'T uses
.lengthpara ver si una colección está vacía. -
EVITA usar
Iterable.forEach()con un literal de función. -
DON'T uses
List.from()a menos que tengas la intención de cambiar el tipo del resultado. -
DO usa
whereType()para filtrar una colección por tipo. -
DON'T uses
cast()cuando una operación cercana servirá. - EVITA usar
cast().
Functions
- DO usa una declaración de función para vincular una función a un nombre.
- DON'T crees una lambda cuando un tear-off servirá.
Variables
-
DO sigue una regla consistente para
varyfinalen variables locales. - EVITA almacenar lo que puedes calcular.
Members
- DON'T envuelvas un campo en un getter y setter innecesariamente.
-
PREFER usar un campo
finalpara hacer una propiedad de solo lectura. -
CONSIDERA usar
=>para miembros simples. -
DON'T uses
this.excepto para redirigir a un constructor con nombre o para evitar sombreado. - DO inicializa campos en su declaración cuando sea posible.
Constructors
- DO usa parámetros de inicialización cuando sea posible.
-
DON'T uses
latecuando una lista de inicializadores de constructor servirá. -
DO usa
;en lugar de{}para cuerpos de constructor vacíos. - DON'T uses
new. -
DON'T uses
constredundante.
Error handling
-
EVITA catches sin cláusulas
on. -
DON'T descartes errores de catches sin cláusulas
on. -
DO lanza objetos que implementan
Errorsolo para errores programáticos. -
DON'T catch explícitamente
Erroro tipos que lo implementan. -
DO usa
rethrowpara relanzar una excepción capturada.
Asynchrony
- PREFER async/await sobre usar futures sin procesar.
-
DON'T uses
asynccuando no tiene ningún efecto útil. - CONSIDERA usar métodos de orden superior para transformar un stream.
- EVITA usar Completer directamente.
-
DO prueba por
Future<T>al desambiguar unFutureOr<T>cuyo argumento de tipo podría serObject.
Diseño
#Names
- DO usa términos consistentemente.
- EVITA abreviaturas.
- PREFER poner el sustantivo más descriptivo al final.
- CONSIDERA hacer que el código se lea como una oración.
- PREFER una frase nominal para una propiedad o variable no booleana.
- PREFER una frase verbal no imperativa para una propiedad o variable booleana.
- CONSIDERA omitir el verbo para un parámetro booleano con nombre parameter.
- PREFER el nombre "positivo" para una propiedad o variable booleana.
- PREFER una frase verbal imperativa para una función o método cuyo propósito principal es un efecto secundario.
- PREFER una frase nominal o frase verbal no imperativa para una función o método si devolver un valor es su propósito principal.
- CONSIDERA una frase verbal imperativa para una función o método si quieres llamar la atención sobre el trabajo que realiza.
-
EVITA comenzar un nombre de función o método con
get. -
PREFER nombrar un método
to___()si copia el estado del objeto a un nuevo objeto. -
PREFER nombrar un método
as___()si devuelve una representación diferente respaldada por el objeto original. - EVITA describir los parámetros en el nombre de la función o método.
- DO sigue las convenciones mnemotécnicas existentes al nombrar parámetros de tipo.
Libraries
- PREFER hacer que las declaraciones sean privadas.
- CONSIDERA declarar múltiples clases en la misma biblioteca.
Classes and mixins
- EVITA definir una clase abstracta de un solo miembro cuando una función simple servirá.
- EVITA definir una clase que contiene solo miembros estáticos.
- EVITA extender una clase que no está destinada a ser subclaseada.
- DO usa modificadores de clase para controlar si tu clase puede ser extendida.
- EVITA implementar una clase que no está destinada a ser una interfaz.
- DO usa modificadores de clase para controlar si tu clase puede ser una interfaz.
-
PREFER definir un
mixinpuro oclasepura en lugar de unaclase mixin.
Constructors
Members
-
PREFER hacer que los campos y las variables de nivel superior sean
final. - DO usa getters para operaciones que conceptualmente acceden a propiedades.
- DO usa setters para operaciones que conceptualmente cambian propiedades.
- DON'T definas un setter sin un getter correspondiente.
- EVITA usar pruebas de tipo en tiempo de ejecución para falsificar la sobrecarga.
-
EVITA campos
late finalpúblicos sin inicializadores. -
EVITA devolver tipos
Future,Streamy colección anulables. -
EVITA devolver
thisdesde métodos solo para habilitar una interfaz fluida.
Types
- DO anota el tipo de variables sin inicializadores.
- DO anota el tipo de campos y variables de nivel superior si el tipo no es obvio.
- DON'T anotes redundante el tipo de variables locales inicializadas.
- DO anota los tipos de retorno en las declaraciones de función.
- DO anota los tipos de parámetros en las declaraciones de función.
- DON'T anotes los tipos de parámetros inferidos en expresiones de función.
- DON'T anotes el tipo de parámetros de inicialización.
- DO escribe argumentos de tipo en invocaciones genéricas que no se infieren.
- DON'T escribas argumentos de tipo en invocaciones genéricas que se infieren.
- EVITA escribir tipos genéricos incompletos.
-
DO anota con
dynamicen lugar de dejar que la inferencia falle. - PREFER firmas en anotaciones de tipo de función.
- DON'T especifiques un tipo de retorno para un setter.
- DON'T uses la sintaxis typedef heredada.
- PREFER tipos de función en línea sobre typedefs.
- PREFER usar sintaxis de tipo de función para parámetros.
-
EVITA usar
dynamica menos que quieras deshabilitar la verificación estática. -
DO usa
Future<void>como el tipo de retorno de miembros asíncronos que no producen valores. -
EVITA usar
FutureOr<T>como un tipo de retorno.
Parameters
- EVITA parámetros booleanos posicionales.
- EVITA parámetros posicionales opcionales si el usuario puede querer omitir parámetros anteriores.
- EVITA parámetros obligatorios que acepten un valor especial de "sin argumento".
- DO usa parámetros de inicio inclusivo y final exclusivo para aceptar un rango.
Equality
Unless stated otherwise, the documentation on this site reflects Dart 3.12.2. Page last updated on 2025-09-04. Ver fuente oreportar un problema.