Guías para una mejor escritura de código Dart

marcelo

Marcelo Sebastián

Posted on August 17, 2020

Guías para una mejor escritura de código Dart

Este es un pequeño recopilatorio de las recomendaciones para escribir un mejor código en Dart proporcionado por su equipo de desarrollo.

Puedes ver el listado completo en Effective Dart.

Índice


Guía de estilo

Reglas para diseñar y organizar el código.

Convención de nombres

En Dart utilizaremos estas tres convenciones:

  • UpperCamelCase la primera letra de cada palabra escrita en mayúscula, incluyendo la primera.
  • lowerCamelCase la primera letra de cada palabra escrita en mayúscula, excepto la primera.
  • lowercase_with_underscores solo usar minúsculas, incluyendo acrónimos y separar las palabras por un subguión "_".

UpperCamelCase

Debemos usar esta convención para nombrar:

  • Classes
  • Enums
  • Typedefs
  • Type parameters
  • Extensions
// Classes (SliderMenu)
class SliderMenu { ... }

// Enums (Color).
enum Color { red, green, blue }

// Typedefs (Predicate).
typedef Predicate<T> = bool Function(T value);

//Type parameters (T).
abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}

// Extensions (MyFancyList).
extension MyFancyList<T> on List<T> { ... }

lowerCamelCase

Debemos usar esta convención para nombrar:

  • Class members
  • Functions
  • Variables
  • Parameters
  • Named parameters
  • Constant/Final names
// Class members (httpRequest).
HttpRequest httpRequest;

// Functions (align).
void align(bool clearItems) {
  // ...
}

// Parameters (clearItems).
void align(bool clearItems) {
  // ...
}

// Named parameters (clearItems).
void align({bool clearItems}) {
  // ...
}

// Constant/Final names (pi, urlScheme).
const pi = 3.14;
final urlScheme = RegExp('^([a-z]+):');

lowercase_with_underscores

Debemos usar esta convención para nombrar:

  • Libraries
  • Packages
  • Directories
  • Source files
  • Named import
library peg_parser.source_scanner;

import 'file_system.dart';

// Named import (angular_components).
import 'package:angular_components/angular_components' as angular_components;

Observaciones

Usar mayúsculas en acrónimos y abreviaturas de más de dos letras.

HttpConnectionInfo
uiHandler
IOStream
HttpRequest
Id
DBIOPort
TVVcr

No colocar un subguión antes de un nombre, a menos que el identificador sea privado.

class Person {
  final _name;
  // ...
}

No usar letras de prefijo, como por ejemplo la Notación húngara.

// Bien.
const defaultTimeout;

// Mal.
const kDefaultTimeout;

Orden

Para una mejor legibilidad en el código se recomienda seguir este orden, y cada sección debe estar separada por una línea en blanco.

Colocar los imports de Dart antes que otros.

import 'dart:async';
import 'dart:html';

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

Colocar los imports de package antes que los imports relativos.

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'util.dart';

Los exports deben estar en una sección separada después de los imports

import 'src/error.dart';
import 'src/foo_bar.dart';

export 'src/error.dart';

Ordenarlos alfabéticamente

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'foo.dart';
import 'foo/foo.dart';

Uso de llaves

Uso normal de llaves.

if (isWeekDay) {
  print('Bike to work!');
} else {
  print('Go dancing or read a book!');
}

Se pueden omitir las llaves si tenemos un if sin else y todo cabe en la misma línea.

if (arg == null) return defaultValue;

Sin embargo aunque el return sea una sola línea pero no cabe en la primera se deben usar llaves.

// Bien.
if (overflowChars != other.overflowChars) {
  return overflowChars < other.overflowChars;
}

// Mal.
if (overflowChars != other.overflowChars)
  return overflowChars < other.overflowChars;

Guía de documentación

Reglas para una correcta documentación de clases o funciones, como comentarios normales.

Comentarios

Usar comentarios en forma de oraciones.
La primera palabra debe empezar con mayúscula, a menos de que sea un identificador Case sensitive.
La línea debe terminar con punto ("." "!" "?"), esto se aplica para todo tipo de comentarios.

// Not if there is nothing before it.
if (_chunks.isEmpty) return false;

No usar comentarios en bloque para documentación.

// Bien.
greet(name) {
  // Assume we have a valid name.
  print('Hi, $name!');
}

// Mal.
greet(name) {
  /* Assume we have a valid name. */
  print('Hi, $name!');
}

Comentarios de documentación

Estos comentarios son especiales porque dartdoc los analiza y crea páginas de documentos para ellos.
Un comentario de documento es cualquier comentario que aparece antes de una declaración y utiliza la sintaxis especial /// que busca dartdoc.

/// The number of characters in this chunk when unsplit.
int get length => ...

Se recomienda empezar los comentarios de la documentación con un resumen de una sola oración.

// Bien.
/// Deletes the file at [path] from the file system.
void delete(String path) {
  ...
}

// MAl.
/// Depending on the state of the file system and the user's permissions,
/// certain operations may or may not be possible. If there is no file at
/// [path] or it can't be accessed, this function throws either [IOError]
/// or [PermissionError], respectively. Otherwise, this deletes the file.
void delete(String path) {
  ...
}

Agrega una línea en blanco después de la primera oración para separar el párrafo.

// Bien.
/// Deletes the file at [path].
///
/// Throws an [IOError] if the file could not be found. Throws a
/// [PermissionError] if the file is present but could not be deleted.
void delete(String path) {
  ...
}

// Mal.
/// Deletes the file at [path]. Throws an [IOError] if the file could not
/// be found. Throws a [PermissionError] if the file is present but could
/// not be deleted.
void delete(String path) {
  ...
}

Evita la redundancia.

Intenta comenzar los comentarios de funciones o métodos con verbos en tercera persona.

/// Returns `true` if every element satisfies the [predicate].
bool all(bool predicate(T element)) => ...

/// Starts the stopwatch if not already running.
void start() {
  ...
}

Puedes utilizar Markdown para documentar, por lo cual puedes incluir ejemplos de código en los comentarios del documento.
Sin embargo se recomienda no abusar del Markdown.

Usa corchetes para hacer referencia a identificadores.

/// Throws a [StateError] if ...
/// similar to [anotherMethod()], but ...

/// Similar to [Duration.inDays], but handles fractional days.

/// To create a point, call [Point()] or use [Point.polar()] to ...

Otros lenguajes usan etiquetas para describir cuáles son los parámetros y los return de un método.

La convención en Dart es integrar eso en la descripción del método y resaltar los parámetros usando corchetes.

//Bien.
/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or
/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) => ...

// Mal.
/// Defines a flag with the given name and abbreviation.
///
/// @param name The name of the flag.
/// @param abbr The abbreviation for the flag.
/// @returns The new flag.
/// @throws ArgumentError If there is already an option with
///     the given name or abbreviation.
Flag addFlag(String name, String abbr) => ...

Evita el uso de abreviaciones.

Prefiere utilizar "this" en lugar de "the" para referirse a instancias.

class Box {
  /// The value this wraps.
  var _value;

  /// True if this box contains a value.
  bool get hasValue => _value != null;
}
💖 💪 🙅 🚩
marcelo
Marcelo Sebastián

Posted on August 17, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related