Creación de un SDK de Flutter, parte 1: desglose de un paquete de Flutter

- Andrés Cruz

Fondo

En mi opinión, generalmente es más fácil escribir un paquete para Flutter en comparación con otros marcos de desarrollo de aplicaciones. Los paquetes no requieren una gran cantidad de conocimientos específicos para crearlos si ya conoces el desarrollo de aplicaciones en Flutter. En otros marcos, los paquetes pueden tener diferentes estructuras y varios métodos de distribución, lo que hace que sea mucho más difícil simplemente comenzar a crear paquetes/bibliotecas.

Cuando nuestro equipo de Flutter comenzó a crear un SDK para nuestro primer producto: Stream Chat (y más tarde Stream Video), comenzó como un paquete simple destinado a facilitar el uso de nuestras API de backend. Sin embargo, a medida que pasó el tiempo, comenzamos a agregarle más funciones: componentes de interfaz de usuario, creadores de interfaz de usuario, almacenamiento fuera de línea, internacionalización y más. Al momento de escribir este artículo, el SDK de Flutter Chat contenía cinco paquetes distintos que permitían diferentes funcionalidades. Tuvimos que iterar el SDK varias veces y probar diferentes arquitecturas, gestión de estado, estructuras de proyectos y mucho más.

Nos damos cuenta de que el conocimiento que hemos adquirido sobre la creación de SDK en Flutter es bastante único. La mayor parte del contenido cubre cada aspecto individual de Flutter. Sin embargo, dado que menos personas crean SDK, el conocimiento se pierde en las páginas de Notion de la empresa o permanece en la mente de quienes lideran los proyectos. Esperamos que este conjunto de artículos te ayude a construir tu SDK en Flutter con relativa facilidad porque creemos que algunas cosas no necesitan aprenderse de la manera más difícil.

Introducción

Definimos un SDK como un conjunto de uno o más paquetes de Flutter que pueden trabajar juntos para lograr un objetivo común, generalmente ayudar a integrar un servicio en una aplicación de Flutter. Sin embargo, antes de que pueda comprender cómo administrar un SDK completo, la función de las partes y archivos individuales de un paquete Flutter es un conocimiento fundamental para cualquier desarrollador.

Este artículo analiza todos los aspectos de un paquete Flutter a través de los archivos presentes (o los que idealmente deberían agregarse) dentro de él. Usamos el SDK Stream Chat Flutter como ejemplo principal y la mayoría de los fragmentos provienen del mismo.

¿Qué es un paquete Flutter?

Un paquete Flutter es una colección de código prediseñada que agrega funcionalidades y características a su aplicación Flutter. Actúan como bloques de construcción, ahorrándole tiempo y esfuerzo al permitirle reutilizar el código existente en lugar de escribirlo todo desde cero. Estos paquetes pueden incluir widgets, bibliotecas, utilidades, activos y más, lo que permite a los desarrolladores integrarlos fácilmente en sus proyectos de Flutter.

También hay una distinción en Flutter entre "paquetes" y "complementos". Los paquetes generalmente se refieren a una colección de código Dart puro, mientras que los complementos se refieren a paquetes con código nativo dentro de ellos. Tenga en cuenta que la palabra "paquete" en esta serie abarca tanto paquetes como complementos, a menos que se indique específicamente lo contrario.

Se puede agregar un paquete a una aplicación a través del archivo pubspec.yaml (que se verá más adelante) a través de la sección de dependencias:

dependencies:

   stream_chat_flutter: 

Paquetes Flutter versus aplicaciones Flutter

El uso final de un paquete Flutter y una aplicación son claramente diferentes. El primero pretende ser un código reutilizable que agrega alguna funcionalidad, mientras que el segundo es una aplicación completa que se puede compilar para cualquier plataforma. Sin embargo, el proyecto inicial de una aplicación y un paquete son similares, casi iguales. Ambos tienen el mismo conjunto de archivos: pubspec.yaml para declaraciones, la carpeta lib para código, la carpeta de prueba y más. La principal diferencia es que aunque estos archivos y carpetas son los mismos, el uso de los archivos es diferente.

{nombre_del_paquete}.dart

En una aplicación normal, el archivo main.dart contiene el punto de entrada de la aplicación a través de la función main(). Toda la ejecución de la aplicación comienza en esta función, que es necesaria para cualquier aplicación Flutter. Dado que un paquete no necesita comenzar a ejecutarse de forma independiente, no necesita contener un punto de entrada main(). Sin embargo, los paquetes contienen su propio archivo central con el mismo nombre que el paquete en la raíz de la carpeta lib. Entonces, el paquete stream_chat tiene un archivo stream_chat.dart dentro de lib. Entonces, ¿para qué sirve este archivo central?

Un paquete contiene varias clases y archivos para lograr la funcionalidad que debe realizar. Sin embargo, no es necesario exponer todas estas clases y métodos. Es posible que incluso sea necesario ocultar algunas cosas específicamente. El objetivo principal del archivo central es definir qué archivos del paquete están expuestos a la aplicación. El archivo también puede exponer otros paquetes que importa.

Supongamos que esta es nuestra estructura de paquete para un paquete de calculadora hipotético: simple_calc

lib/
 simple_calc.dart
 calculator.dart
 utils/
   math_utils.dart
 models/
number_model.dart

En esta estructura, el archivo simple_calc.dart es el archivo central antes mencionado. Es posible que queramos exponer la clase de calculadora y number_model.dart, pero no math_utils.dart. Usamos la palabra clave export para exponer archivos a la aplicación.

Para ello, el archivo simple_calc.dart tendrá este aspecto:

export 'calculator.dart';
export 'models/number_model.dart';

No es necesario que ocultes nada específicamente si no quieres exponerlo. Todos los archivos no exportados están ocultos de forma predeterminada. Puede utilizar las palabras clave mostrar y ocultar para mostrar solo ciertas cosas u ocultar ciertas cosas respectivamente. Por ejemplo, digamos que solo queremos mostrar la clase de calculadora del archivo calculadora.dart y ocultar una clase Número Imaginario del archivo number_model.dart.

Así escribiríamos el escenario mencionado:

export 'calculator.dart' show Calculator;
export 'models/number_model.dart' hide ImaginaryNumber;

Algo a tener en cuenta es que la convención general al crear paquetes es agregar una carpeta src dentro de la carpeta lib que incluye todo excepto el archivo central. Esto permite la separación entre el archivo central y el código fuente del paquete.

La nueva estructura con los mismos archivos sería:

lib/
 simple_calc.dart
 src/
  calculator.dart
  utils/
    math_utils.dart
   models/
    number_model.dart

pubspec.yaml

En general, el archivo pubspec.yaml de una aplicación es una combinación de metadatos sobre un proyecto y las dependencias que importa. El pubspec.yaml que pertenece a un paquete es similar al que pertenece a una aplicación, pero contiene metadatos diferentes en comparación con una aplicación y ciertas restricciones adicionales para las dependencias.

Dado que el archivo es un archivo YAML, contiene varias propiedades sobre el paquete. Repasemos algunas de las posibles propiedades que puede establecer en el archivo. Puede que esta no sea una lista exhaustiva; sin embargo, estas son algunas de las propiedades principales que se utilizan al crear un paquete.

name: Define el nombre del paquete. Este es el nombre que aparecerá en pub.dev cuando se publique un paquete.

name: stream_chat

versión: Define la versión del paquete. Flutter permite varios tipos de sistemas de control de versiones, como un número de versión normal ("1.0.0"), una versión parcheada ("1.0.0+2") o incluso una etiqueta diferente que se puede publicar como prelanzamiento ( "2.0.0-beta.1" / "2.0.0-dev.1").

version: 8.0.0
# or version: 8.0.0+1
# or version: 8.0.0-beta.1

descripción: agrega una descripción de la funcionalidad del paquete que es la línea de descripción principal debajo del nombre del paquete en pub.dev.

description: The official Dart client for Stream Chat, a service for building chat applications.

repositorio: el campo repositorio, que no es obligatorio, incluye la URL del repositorio de código fuente de su paquete. Si decide publicar su paquete en pub.dev, la página principal mostrará la URL del repositorio. Aunque no es obligatorio, le recomendamos que proporcione el repositorio o la página de inicio (o ambos), ya que ayuda a los usuarios a comprender el origen de su paquete.

repository: <https://github.com/GetStream/stream-chat-flutter>

página de inicio: esta URL debe vincular al sitio web de su paquete. En el caso de paquetes alojados, se puede acceder a esta URL desde la página principal del paquete.

homepage: <https://github.com/GetStream/stream-chat-flutter>

issues_tracker: el campo opcional issues_tracker debe incluir una URL que dirija al rastreador de problemas del paquete, lo que ayuda a los usuarios a ver los errores existentes y presentar otros nuevos. En los casos en los que issues_tracker está ausente pero el repositorio está presente y dirige a GitHub, el sitio pub.dev utiliza de forma predeterminada el rastreador de problemas en la página de problemas del repositorio.

issue_tracker: <https://github.com/GetStream/stream-chat-flutter/issues>

documentación: algunos paquetes tienen un sitio dedicado para alojar la documentación, distinto de la página de inicio principal y la referencia de API generada por pub.dev. Incluya un campo de documentación que contenga la URL respectiva si su paquete incluye documentación complementaria. Pub mostrará un enlace a esta documentación en la página principal de su paquete.

temas: al publicar un paquete, pub.dev identifica automáticamente las plataformas que admite. En caso de que esta lista sea incorrecta, utilice el atributo de plataformas para especificar explícitamente las plataformas admitidas. Por ejemplo, la siguiente entrada de plataforma garantiza que pub.dev incluya el paquete como compatible con Android, iOS, Linux, macOS, Web y Windows:

platforms:
   android:
   ios:
   linux:
   macos:
   web:
   windows:

publicar_to: de forma predeterminada, los paquetes se publican en pub.dev. Puede usar Publish_to para publicar sus paquetes en otro servidor personalizado o dejar de publicar cualquier cosa por completo.

publish_to: none

Si desea publicar en su propio servidor, consulte esta publicación en los documentos de Flutter para obtener más información.

LICENCIA

El archivo LICENCIA es un componente crucial que describe los términos de la licencia bajo los cuales se distribuye el código del paquete y puede ser utilizado por otros. La concesión de licencias es fundamental en el desarrollo de software de código abierto, ya que define cómo los desarrolladores y las organizaciones pueden utilizar, modificar y distribuir el código.

Estas son algunas de las licencias más comunes utilizadas por un paquete Flutter:

  • Licencia MIT: Esta es una de las licencias más permisivas. Permite a los usuarios hacer casi cualquier cosa que quieran con el código siempre que incluyan el aviso de licencia y derechos de autor originales en cualquier copia del software/fuente.
  • Licencia Apache: Otra licencia permisiva, la Licencia Apache, permite a los usuarios usar, modificar y distribuir el código bajo ciertas condiciones. También proporciona una concesión expresa de derechos de patente de los contribuyentes a los usuarios.
  • Licencia BSD: Al igual que la licencia MIT, la licencia BSD es una licencia permisiva que permite una amplia gama de usos, pero tiene un conjunto de condiciones ligeramente diferente con respecto a la redistribución.
  • GPL (Licencia Pública General GNU): Esta es una licencia copyleft, lo que significa que los trabajos derivados deben licenciarse bajo los mismos términos. Existen diferentes versiones de la GPL, como
  • GPL-2.0 y GPL-3.0, cada una con sus disposiciones específicas.
  • LGPL (Licencia pública general reducida GNU): similar a la GPL, la LGPL también es una licencia copyleft pero tiene requisitos de vinculación de bibliotecas menos estrictos.
    Tenga en cuenta que también puede crear su propia licencia personalizada si desea que alguna parte de su código sea propietario o de pago

README.md

El archivo README.md en un paquete Flutter es una fuente principal de documentación e información para los desarrolladores interesados en utilizar el paquete. Por lo general, contiene detalles esenciales sobre el paquete, sus características, instrucciones de instalación, ejemplos de uso y otra información útil.

El README es a menudo el único archivo que los desarrolladores leen al evaluar un paquete, así que asegúrese de incluir un ejemplo sólido de lo que el paquete puede hacer y las características que atraerían a los usuarios potenciales.

CHANGELOG.md

El archivo CHANGELOG.md en un proyecto Flutter sirve como un registro histórico de todos los cambios y actualizaciones realizados en el proyecto a lo largo del tiempo. Ayuda a los usuarios a mantenerse informados sobre nuevas funciones o mejoras, correcciones de errores, cambios importantes y actualizaciones de versiones generales.

CONTRIBUTING.md

La mayoría de los paquetes Flutter publicados en pub.dev son proyectos de código abierto. Como todos los proyectos de código abierto, a menudo dependen de las contribuciones de la comunidad para mantener el proyecto en marcha. Para hacerlo, los contribuyentes potenciales necesitan conocer más detalles sobre el repositorio, como cualquier información sobre el paquete de estructura, los pasos necesarios para ejecutar y probar el código, y más. Todas las reglas y procesos, configuraciones de linter, etc., deben compartirse entre los contribuyentes.

Además, cuando un proyecto de código abierto recibe muchos contribuyentes, resulta tedioso solicitar las mismas cosas a cada uno de ellos: documentación, pruebas, detalles de trabajo, etc. Es posible que todos los contribuyentes también deban firmar un acuerdo si una empresa es propietaria del paquete.

Para que estos escenarios sean más fáciles de manejar, la mayoría de los paquetes grandes agregan un documento al repositorio llamado CONTRIBUTING.md (pero en realidad puedes nombrarlo como quieras siempre que sea obvio para quién es) que especifica todos los detalles mencionados.

Aquí hay un fragmento del archivo [CONTRIBUTING.md](<http://CONTRIBUTING.md>) de Stream:

Publicar un paquete Flutter

Cuando termine de implementar la funcionalidad dentro de su paquete Flutter, es hora de publicar.

Antes de publicar, aquí hay algunos pasos que nosotros (y la publicación) recomendamos seguir:

Formatee su código con el formateador pubspec (formato dart).
Ejecute el comando pana para verificar y analizar cualquier problema con su paquete.
Verifique que tenga configurado su archivo de LICENCIA (para la primera vez que lo carga) y que CHANGELOG.md y pubspec.yaml estén actualizados con los cambios más recientes.
Para publicar un paquete Flutter, simplemente puede ejecutar el siguiente comando en su paquete:

flutter pub publish

Sin embargo, antes de hacerlo, le recomendamos realizar un ensayo de su publicación agregando la misma marca:

flutter pub publish --dry-run

Tenga en cuenta que puede usar un paquete sin publicarlo en pub.dev; esto se hace importando un paquete desde GitHub de esta manera:

dependencies:
   packageA:
     git:
       url: <https://github.com/flutter/packageA.git>

Tenga en cuenta que las últimas confirmaciones se obtendrán de esta manera y el control de versiones se vuelve difícil cuando se utiliza este método.

También puedes evitar la publicación por completo y usar un paquete de un repositorio privado usando SSH:

dependencies:
   packageA:
     git:
       url: git@github.com:flutter/packageA.git

Artículo original:

https://medium.com/flutter-community/building-a-flutter-sdk-part-1-breaking-down-a-flutter-package-49fe36ec4b4b

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.