Version 19 (modified by 15 years ago) (diff) | ,
---|
TolPackage: Un sistema de desarrollo modular en red
Objetivos
El objetivo principal de este sistema es que los usuarios finales que no colaboran en el desarrollo de las librerías de uso más o menos genérico, no tengan que preocuparse de dónde se encuentra el código fuente de las mismas ni tenga que tener instalados programas para compartir código como CSV o SVN. El usuario sólo necesita saber una URL remota o un camino local donde se encuentran los paquetes y el nombre de los que necesita. El sistema se ocupa de instalar todo lo necesario de forma automática si se desea o manualmente si se trata de procesos críticos.
El otro gran objetivo es fomentar la creación de utilidades concretas que se puedan cargar atómicamente sin necesidad de compilar cantidades ingentes de código del cual luego se usa sólo una pequeña parte la mayor parte de las veces. El usuario no necesita saber qué paquetes dependen de cuáles sino que son ellos mismos quienes se autogestionan.
También resulta de vital importancia permitir que cada paquete evolucione sin excesivas ataduras de compatibilidad hacia atrás para que pueda progresar pero sin dejar tirados a los usuarios que por motivos de seguridad no pueden arriesgarse a actualizarse cada poco tiempo.
Por último, debe ser muy fácil de usar. Una vez cargado, el paquete es siempre global aunque se haya llamado desde un ámbito local puesto que tratándose de herramientas de uso general no tiene sentido tener tantos miramientos. Como contrapartida, un paquete no se puede descargar de la memoria una vez que ha sido cargado, pero eso tampoco es problema puesto que no ocupan un espacio significativo en comparación con los datos de los problemas que pueden resolver.
Arquitectura
Un paquete es un tipo de NameBlock especial que se carga con la orden
#Require nombre_de_paquete;
y que se lee directamente de un archivo OIS almacenado previamente en un directorio local predeterminado por el sistema al que llamaremos almacén del cliente y que es común para todas las instalaciones de TOL que haya en una misma máquina.
Un repositorio es un sitio web o un directorio local al que llamaremos también almacén servidor, donde se encuentra disponible una colección de paquetes ya preparados para que los usuarios puedan descargarlos a su almacén de cliente.
Los paquetes disponibles en repositorios remotos o locales se instalan,
actualizan y manejarlos mediante las utilidades de
StdLib::TolPackage::Client
Las utilidades para la creación de repositorios se encuentran en
StdLib::TolPackage::Server
Creación y uso de paquetes
Un paquete se crea como un NameBlock pero con una serie de restricciones de obligado cumplimiento
Estructura
- Debe crearse en un fichero principal del mismo nombre con extensión .tol y dentro de un directorio raíz llamado igual. El fichero principal puede cargar con #Embed los archivos auxiliares que necesite con nombre libre pero ubicación paralela o en subdirectorios del raíz.
- Los miembros obligatorios del NameBlock de un paquete son:
Text _.autodoc.brief = "Descripción cortísima en una línea". Text _.autodoc.description = "Descripción detallada"; }}} Text _.autodoc.url = "http://.../"; }}} Set _.autodoc.keys = [["Palabras","Clave", ...]]; }}} Set _.autodoc.authors = [[ "fulanito@mail.tal", "menganito@mail.cual"]]; }}} Text _.autodoc.minTolVersion = Copy(TolReleaseId); Real _.autodoc.version.high = 1; Real _.autodoc.version.low = 1; Set _.autodoc.dependencies = [["paquete1","paquete2", ...]];
- Cuando un paquete requiera para su ejecución de recursos ajenos a TOL será
necesario añadir un nuevo miembro que será un conjunto de conjuntos de
caminos a los directorios raíces de cada uno de los recursos. Los que sean
independientes de la plataforma se pueden poner en un elemento
crossPlatform
y los que sí dependan en uno con el nombre de la plataforma. Los nombres de los recursos han de ser únicos dentro de cada plataforma específica y serán lógicamente los mismos en todas ellas, pues los recursos deberían estar disponibles en cualquiera de ellas, aunque podría haber excepciones si no se encuentra la forma de implementarlo en alguna. Los recursos multi-plataforma deben tener nombres únicos distintos de los de las específicas pues en el almacén de cliente convivirán con ellos en un mismo directorio.
Set _.autodoc.nonTolResources = { [[ Set crossPlatform = { [[ Text resource_cross_1="./....", Text resource_cross_2="./....", ... ]] }, Set win32_x86 = { [[ Text resource_1="./....", Text resource_2="./....", ... ]] }, Set linux_x86 = { [[ Text resource_1="./....", Text resource_2="./....", ... ]] }, ... ]] };
Nomenclatura y versionado
- Los nombres de los paquetes deben seguir el estilo CamelCase
- No puede haber paquetes con el mismo nombre de NameBlock ni en el mismo ni en distinto repositorio, pues todos los paquetes compartirán un mismo almacén de cliente vengan del repositorio que vengan.
- El nombre del archivo de una versión concreta de un paquete se obtiene como la concatenación del nombre del paquete seguido de un punto, el número _.autodoc.version.high, otro punto y el número _.autodoc.version.low
- El nombre del NameBlock sin embargo es el mismo siempre, por lo que se invocará sin usar los números de versión.
- No es posible por tanto cargar dos versiones distintas de un mismo paquete en la misma sesión TOL.
- Sí es posible cargar diferentes versiones de un mismo NameBlock en una misma máquina en sesiones de TOL distintas, coincidentes o no en el tiempo.
Código declarativo
- Puesto que un paquete se almacena como un módulo OZA, está terminantemente
prohibido que un NameBlock ejecute acciones de ningún tipo durante su creación.
Si se hace algo así el sistema no avisará pero simplemente no se realizarán las
acciones previstas. Es decir, las declaraciones de los miembros no pueden tener
efectos secundarios como
- Cambiar parámetros globales de TOL
PutEditor, PutLanguage, PutDefaultDates, PutDumpFile, PutTableRealFormat, PutTableDateFormat, PutRealFormat, PutDateFormat
- Modificar variables con
PutValue, :=, PutName, PutSerDat, PutMatDat, PutVMatDat, PutVMatBlock, PutCoef SetIndexByName, Append
- Llamar al sistema operativo
FileDelete, FileRename, FileCat, MkDir, System, ShellExecute, WinSystem, ChildProcess, WinRmtSystem, WinRmtKill, WinRmtProcessAlive
- Llamar a funciones del interfaz
Tcl_Eval, Tcl_EvalEx
- Abrir ficheros
ShowFile,WriteFile,AppendFile MatWriteFile,MatAppendFile,VMatPrint BDTFile,BSTFile,BMTFile,StatFile,BSIFile FOpen,FGetText,FPutText,FEof,FFlush,FClose
- Abrir conexiones a la base de datos o a cualquier otro mecanismo de consulta.
DBOpen,DBActivate,DBGetOpened,DBClose,DBExecQuery, DBSeries,DBSeriesColumn,DBSeriesTable, DBMatrix,DBTable,DBCreateSeriesTable,DBTableColumn, BDBExtract,BDBSaveAs,BDBSeries, BDBClassify,BDBSortAndSave,BDBSort, BDBCell,BDBRead,BDBTable,BDBReg,BDBLine, BDBFieldPos,BDBClose,BDBOpen
- Uso de
MakeGlobal
(De hecho no debería usarse nunca)
- Cambiar parámetros globales de TOL
- Como excepción a lo anterior sí está permitido el uso de
PutStructure
ya que se emplea a menudo como mecanismo de documentación interna del código fuente. - Si un paquete necesita ejecutar alguna acción antes de ser utilizado deberá
tener un método
Real StartActions(Real void) { ... };
el cual será llamado justo después de ser cargado por el #Require por vez primera. En el caso de que el paquete contenga recursos ajenos a TOL, el métodoStartActions
será quien se ocupe de terminar de inicializar lo que corresponda a esos recursos. Para ello sólo necesita saber el path local que se obtiene llamando a
Text TolPackage::Client::LocalResourcePath(Text package.version, Text resource)
Dependencias
- Cuando un paquete requiere de otros se debe incluir las correspondientes sentencias #Require antes de la declaración del primer miembro.
- Si no se especifican números de versión el #Require cargará la versión más actual compatible con la versión de TOL que se esté ejecutando. En el caso de la última versión de TOL, corresponderá al archivo con el nombre del paquete nada más. En este caso, los paquetes que requiera directa o indirectamente serán también las últimas versiones compatibles con TOL.
- Si se solicita una versión concreta, entonces se debe cargar previamente cada
uno de los paquetes requeridos directa o indirectamente. El propio
#Require
se encargará de buscar las versiones adecuadas en el repositorio local, de instalarlas si no las encuentra, y de dar un mensaje de error si no lo consigue para que se haga manualmente. - Téngase en cuenta que no es posible cargar versiones concretas de paquetes que tengan requerimientos de diferentes versiones de un mismo paquete.
- La definición del paquete siempre debe usar #Require sin especificar una versión concreta.
- Obsérvese que los paquetes requeridos se deben especificar por duplicado: primero en los #Require sin comillas y luego en Set _.autodoc.dependencies entre comillas pues esta información la necesita el gestor de repositorios.
- No está permitido el requerimiento cíclico directo ni indirecto entre paquetes, es decir, si A requiere a B directa o indirectamente B no puede requerir a A ni directa ni indirectamente. El sistema gestor de repositorios caería en un ciclo infinito y no hay forma de detectarlo luego es responsabilidad de los desarrolladores del repositorio el evitarlo.
Documentación y chequeo de calidad
- Cada paquete debe estar dotado de documentación autocontenida de manera que cualquier usuario pueda aprender a usarlo por sí mismo. Queda por ver si esa documentación ha de ser WIKI, HTML, PDF, ASCII, o si puede ser opcional el formato. La documentación estará ubicada en cualquier caso dentro de un directorio doc colgando directamente de la raíz del paquete.
- También debe tener una batería de tests estándar en un directorio test colgando directamente de la raíz del paquete.
En tolp/OfficialTolArchiveNetwork pueden verse ejemplos de paquetes. Cada subdirectorio es un paquete.
Creación de repositorios
En el archivo tolp/OfficialTolArchiveNetwork/_upload.tol puede verse como ejemplo el programa de creación y subida de OfficialTolArchiveNetwork, el repositorio oficial de paquetes del equipo de desarrollo de TOL.
- El repositorio es un directorio con unos archivos y directorios obligatorios:
- archivos:
- index.tol: Contiene características generales del repositorio como el nombre, el tipo ("Private" ó "Public") y la descripción de los objetivos.
- index.csv: Listado de los paquetes y su información asociada: fecha, versión, dependencias, etc.
- subdirectorios:
- register: Un fichero para cada paquete con un solo registro de información relativa al mismo.
- packages: Los paquetes propiamente dichos, es decir, los archivos con extensión .oza listos para su descarga.
- export: contiene un subdirectorio por cada paquete con los códigos fuente originales, la documentación, los tests y todo aquello que se usó en la construcción. Funciona al mismo tiempo como un backup y como una forma de enlazar URL's a lo que haga falta del paquete.
- resources:
El servidor de creación de los paquetes se encargará de leer los recursos
ajenos a TOL de
_.autodoc.nonTolResources
, comprimir los directorios enumerados y enviarlos al repositorio remoto dentro de este subdirectorio. También quedarán anotados en el archivo de índice en el campo de dependencias externas. El instalador del cliente se los bajará al mismo tiempo que el .oza los recursos comprimidos que correspondan a su plataforma, incluyendo los que son independientes de la plataforma, creando para ello un directorio propio del paquete
TolPackage::Client::_.localRoot+package.version+"/"
Luego descomprimirá ahí dentro cada uno de los recursos descargados de forma que sean accesibles localmente.
- archivos:
- Debería haber un comité o alguien responsable de probar todos los paquetes de un repositorio antes de publicar las actualizaciones de los paquetes para asegurar la compatibilidad conjunta de todos ellos.