Organiza el código Dart con paquetes y librerías
Aprende cómo organizar tu código Dart en librerías y paquetes reutilizables.
En este capítulo, pasarás de la sintaxis básica de Dart a construir aplicaciones de línea de comandos "al estilo Dart", adoptando las buenas prácticas. Aprenderás a refactorizar tu código en componentes reutilizables creando un paquete dedicado para manejar los argumentos de línea de comandos.
Este paso te prepara para construir una aplicación de línea de comandos
más avanzada en los próximos capítulos,
que integrará paquetes especializados para la
lógica de Wikipedia y un framework de command_runner robusto.
Este capítulo te ayuda a entender las librerías de Dart, las sentencias de exportación y
cómo estructurar tu proyecto para una mejor organización y mantenibilidad.
Qué lograrás
Prerrequisitos
#- Haber completado el Capítulo 3, que cubrió programación asíncrona y solicitudes HTTP.
Tareas
#En este capítulo, refactorizarás la
aplicación de CLI dartpedia existente extrayendo
la lógica de parseo de argumentos de línea de comandos en
un paquete separado llamado command_runner.
Esto mejorará la estructura de tu proyecto,
haciéndolo más modular y mantenible.
Tarea 1: Crear el paquete command_runner
#Primero, crea un nuevo paquete Dart para albergar la lógica de parseo de argumentos de línea de comandos.
Navega al directorio raíz de tu proyecto (
/dartpedia).-
Ejecuta el siguiente comando en tu terminal:
bashdart create -t package command_runnerEste comando crea un nuevo directorio llamado
command_runnercon la estructura básica de un paquete Dart. Ahora deberías ver una nueva carpetacommand_runneren la raíz de tu proyecto, junto con tu paquetecli.
Tarea 2: Implementar la clase CommandRunner
#Ahora que has creado el paquete command_runner,
añade una clase de marcador de posición (placeholder) que eventualmente
manejará la lógica de parseo de argumentos de línea de comandos.
-
Abre el archivo
command_runner/lib/command_runner.dart. Elimina cualquier código de marcador de posición existente y agrega lo siguiente:dart/// A simple command runner to handle command-line arguments. /// /// More extensive documentation for this library goes here. library; export 'src/command_runner_base.dart'; // TODO: Export any other libraries intended for clients of this package.Aspectos destacados del código anterior:
library;declara este archivo como una librería, lo que define los límites y la interfaz pública de una unidad reutilizable de código Dart.export 'src/command_runner_base.dart';es una línea crucial que hace que las declaraciones decommand_runner_base.dartestén disponibles para otros paquetes que importen el paquetecommand_runner. Sin esta sentenciaexport, las clases y funciones dentro decommand_runner_base.dartserían privadas para el paquetecommand_runner, y no podrías usarlas en tu aplicacióndartpedia.
Abre el archivo
command_runner/lib/src/command_runner_base.dart.-
Elimina cualquier código de marcador de posición existente y añade la siguiente clase
CommandRunneracommand_runner/lib/src/command_runner_base.dart:dartclass CommandRunner { /// Runs the command-line application logic with the given arguments. Future<void> run(List<String> input) async { print('CommandRunner received arguments: $input'); } }Aspectos destacados del código anterior:
CommandRunneres una clase que sirve como un sustituto simplificado por ahora. Su métodorunactualmente solo imprime los argumentos que recibe. En capítulos posteriores, expandirás esta clase para manejar un parseo de comandos complejo y configurable.- El tipo de retorno
Future<void>indica que este método podría realizar operaciones asíncronas, pero no devuelve un valor.
Tarea 3: Agregar command_runner como una dependencia
#
Ahora que has creado el paquete command_runner y
añadido una clase CommandRunner de marcador de posición, necesitas
decirle a tu aplicación cli que depende de command_runner.
Debido a que el paquete command_runner está ubicado localmente dentro de tu proyecto,
puedes usar una dependencia de ruta (path dependency).
-
Abre el archivo
cli/pubspec.yaml. -
Debido a que el paquete
clies un paquete de aplicación y no está destinado a ser publicado en pub.dev, añadepublish_to: nonedespués del camponame. Esto ayuda a evitar la publicación accidental y previene advertencias del analyzer al añadir dependencias de ruta.yamlname: cli publish_to: none # ... -
Localiza la sección
dependencies. Agrega las siguientes líneas:yamldependencies: http: ^1.3.0 # Keep your existing http dependency command_runner: path: ../command_runner # Points to your local command_runner packageEsta sección le indica a la aplicación
clique depende del paquetecommand_runner, y especifica que el paquete está ubicado en el directorio../command_runner(relativo al directoriocli). -
Ejecuta
dart pub geten el directorio/dartpedia/clide tu terminal para obtener la nueva dependencia.
Tarea 4: Importar y usar el paquete command_runner
#
Ahora que has agregado command_runner como una dependencia,
puedes importarlo en tu aplicación cli y
reemplazar tu lógica de manejo de argumentos existente con
la nueva clase CommandRunner. Este paso también
corrige el comportamiento de salida del programa discutido al final del Capítulo 3.
Abre el archivo
cli/bin/cli.dart.-
Agrega la siguiente sentencia de importación en la parte superior del archivo, junto con tus otras importaciones:
dartimport 'package:command_runner/command_runner.dart';Esta sentencia importa el paquete
command_runner, haciendo que la claseCommandRunneresté disponible para su uso. -
Refactoriza la función
mainy elimina la lógica antigua: Actualmente, tu funciónmaindel Capítulo 3 maneja directamente comandos comoversion,helpywikipedia, y luego llama asearchWikipedia. Ahora reemplazarás toda esta lógica personalizada de manejo de comandos con una sola llamada a la nueva claseCommandRunner.Tu archivo
cli/bin/cli.dart(del Capítulo 3) debería verse así actualmente:dartimport 'dart:io'; import 'package:http/http.dart' as http; import 'package:command_runner/command_runner.dart'; const version = '0.0.1'; void main(List<String> arguments) { if (arguments.isEmpty || arguments.first == 'help') { printUsage(); } else if (arguments.first == 'version') { print('Dartpedia CLI version $version'); } else if (arguments.first == 'wikipedia') { final inputArgs = arguments.length > 1 ? arguments.sublist(1) : null; searchWikipedia(inputArgs); } else { printUsage(); } } void searchWikipedia(List<String>? arguments) async { /* ... existing logic ... */ } void printUsage() { /* ... existing logic ... */ } Future<String> getWikipediaArticle(String articleTitle) async { /* ... existing logic ... */ }**Ahora, reemplaza todo el contenido de
cli/bin/cli.dart(excepto la importación dehttp) con la siguiente versión actualizada:dartimport 'dart:io'; import 'package:http/http.dart' as http; import 'package:command_runner/command_runner.dart'; void main(List<String> arguments) async { // main is now async and awaits the runner var runner = CommandRunner(); // Create an instance of your new CommandRunner await runner.run(arguments); // Call its run method, awaiting its Future<void> }Aspectos destacados del código anterior:
void main(List<String> arguments) asyncaborda directamente el problema de que el programa no finalizaba limpiamente del Capítulo 3. Nota quemainahora está declarada comoasync. This es esencial porquerunner.run()devuelve unFuture, ymaindebe hacerawaitde su completación para asegurar que el programa espere a que todas las tareas asíncronas terminen antes de salir.var runner = CommandRunner();crea una instancia de la claseCommandRunnerde tu nuevo paquetecommand_runner.await runner.run(arguments);llama al métodorunen la instancia deCommandRunner, pasando los argumentos de la línea de comandos.
Funciones eliminadas:
- Las funciones
printUsage,searchWikipediaygetWikipediaArticleahora están completamente eliminadas decli/bin/cli.dart. Su lógica se rediseñará y se moverá al paquetecommand_runneren futuros capítulos, como parte de la construcción del framework completo de línea de comandos.
Tarea 5: Ejecutar la aplicación
#Ahora que has refactorizado el código y
actualizado la aplicación cli para usar el paquete command_runner,
ejecuta la aplicación para verificar que todo
esté funcionando correctamente en esta etapa.
Abre tu terminal y navega al directorio
cli.-
Ejecuta el comando
wikipedia:bashdart run bin/cli.dart wikipedia Computer_programming -
Asegúrate de que la aplicación ahora se ejecute sin errores e imprima los argumentos en la consola, demostrando que el control se ha transferido con éxito a tu nuevo paquete
command_runner.bashCommandRunner received arguments: [wikipedia, Computer_programming]
Revisión
#Qué lograste
Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.Creaste un paquete Dart reutilizable
Usaste dart create -t package command_runner para estructurar un nuevo paquete de librería destinado a ser utilizado en otros paquetes. Los paquetes de librería son la forma estándar de organizar y compartir librerías de Dart reutilizables, ya sea dentro de un workspace de proyecto o publicados en pub.dev.
Usaste exportaciones para definir una API pública
Añadiste sentencias export en tu archivo de librería para exponer librerías específicas y sus definiciones a los consumidores. Si no se exporta desde archivos en el
directorio raíz lib, el código en lib/src/ permanece privado para el paquete. Esto te permite diseñar cuidadosamente una API pública para otros, mientras mantienes un control total sobre los detalles de implementación.
Agregaste dependencias de ruta local
Configuraste pubspec.yaml para depender de un paquete local usando una dependencia de ruta. Esto permite proyectos multipaquete donde los paquetes pueden evolucionar juntos antes de ser publicados por separado.
Cuestionario
#Pon a prueba tu comprensión
1 / 3export statement in a Dart library?Para hacer que las declaraciones de otros archivos estén disponibles a través de la API pública de tu librería.
¡Correcto!
Exportar te permite volver a exponer declaraciones. Por ejemplo,
export 'src/command.dart';hace queCommandsea accesible para cualquiera que importe tu paquete.Para importar múltiples librerías con una sola sentencia.
No exactamente.
importeexportsirven para propósitos diferentes.importhace que el código esté disponible para tu librería, mientras queexporthace algo para los consumidores de tu librería.Para ocultar detalles de implementación de otras librerías.
No exactamente.
La sentencia
exporthace lo contrario a ocultar. Para ocultar miembros que son solo de implementación, no los incluyas en ninguna sentencia export.Para especificar qué versiones del SDK de Dart soporta tu paquete.
No exactamente.
Las restricciones de SDK van en
pubspec.yaml, no en el código Dart.exportes una característica del lenguaje Dart, no una opción de configuración.
Usar una restricción de versión como
command_runner: ^1.0.0.No exactamente.
Las restricciones de versión son para paquetes publicados en pub.dev. Los paquetes locales requieren un tipo diferente de especificación de dependencia.
Usar una dependencia de ruta (path dependency) como
command_runner: {path: ../command_runner}.¡Correcto!
Las dependencias de ruta (path dependencies) apuntan a un directorio local. Esto es perfecto para proyectos multipaquete o para desarrollar paquetes antes de publicarlos.
Copiar la carpeta del paquete en el directorio
lib/de tu proyecto.No exactamente.
Copiar crea duplicación y problemas de versiones. Dart proporciona una forma de referenciar paquetes por su ubicación sin copiarlos.
Ejecutar
dart pub add command_runner --localNo exactamente.
No hay una bandera
--localparadart pub add. Debes especificar la ubicación de manera diferente enpubspec.yamlo pasando un descriptor de paquete adart pub add.
lib/src/parser.dart. Why might you create lib/parser.dart that just contains export 'src/parser.dart';?Para permitir a los usuarios importar desde una ruta limpia mientras se mantienen los archivos de implementación organizados en
src/.¡Correcto!
Los usuarios pueden escribir
import 'package:mylib/parser.dart';en lugar de buscar dentro desrc/. Esto separa tu API pública de la organización interna.Para hacer que el código se ejecute más rápido al reducir la profundidad de la importación.
No exactamente.
Exportar no afecta al rendimiento en tiempo de ejecución. El número de directorios en una ruta de importación no tiene impacto en la velocidad del código.
Porque Dart requiere que todos los archivos públicos estén en el directorio raíz
lib/.No exactamente.
Dart no requiere esta estructura. Es una convención, no un requisito del lenguaje.
Para evitar que otros paquetes importen los archivos de
src/directamente.No exactamente.
Técnicamente, los archivos en
src/aún se pueden importar directamente. Las buenas prácticas de Dart lo desaconsejan, pero no lo impiden.
Siguiente lección
#En el próximo capítulo, te sumergirás en los
conceptos de la programación orientada a objetos (OOP) en Dart.
Aprenderás cómo crear clases, definir relaciones de herencia y
construir un framework de parseo de argumentos de línea de comandos más robusto utilizando
principios de OOP dentro de tu nuevo paquete command_runner.
A menos que se indique lo contrario, la documentación de este sitio refleja Dart 3.12.2. Página actualizada por última vez el 09-04-2026. Ver fuente oreportar un problema.