Scripting mIRC Optimización
by Arphean
Este artículo describe los puntos más
importantes para considerar la optimización en la escritura de código para
mIRC.
Muchas discusiones se han llevado a cabo a este respecto, y muchos
autores consideran la optimización una razón importante para la programación,
necesaria pero que no se suele usar. Intentaré realizar la descripción de un uso
de la eficiencia no sólo desde el punto de vista de la ejecución, sino de la
optimización de código, así como de la reutilización y actualización. También
trataré de ir descubriendo técnicas para tratar de hacer el resultado final más
intuitivo y eficiente, descubriendo cómo puedes realmente optimizar tu
código.
Aunque existen muchos y muy buenos artículos sobre depuración de
código para mIRC Scripting, no me he basado en ninguno de ellos. Quiero decir
que éste no es un artículo realizado a partir de otros artículos de mIRC, sino
enfocado a un acercamiento sobre una programación más seria del lenguaje.
El
nivel de este artículo es para programadores ya avanzados.
Rapidez o estabilidad
La
mayoría de las personas scripters suelen confundir rapidez con optimización.
Así, cuando intentan hacer valer sus argumentos, explican, mediante código, que
su realización es más rápida.
Como se sabe ya desde hace mucho tiempo, la
rapidez muchas veces está reñida con la estabilidad en cuanto a la programación
se refiere. Yo puedo elegir realizar un bucle mucho más rápido que la
realización de la llamada a un alias. Sin embargo, cuando estamos operando con
características reales, no suele ser la mejor opción.
Por ejemplo,
imaginémonos que debemos realizar un bucle que tome como parámetro de entrada
los usuarios de un canal y nos dé como salida una sencilla cadena con todos
ellos.
Mediante un bucle while se podría obtener inmediatamente el resultado,
pero ¿qué pasaría si el parámetro de entrada se retrasara unos segundos? Pues
nos devolvería una cadena partida, errónea o, incluso, no devolvería
nada.
Para solucionar este problema se suele utilizar un retraso virtual, que
puede ser un contador o un timer. De esta forma, aun evitando la posible nula
salida, tendremos como resultado que, lo que al principio pensabamos realizar
eficientemente y rápido, nos encontramos ahora con un código dependiente,
enlentecido e inestable. Si añadimos un timer para esperar a tener todos los
valores de entrada, un timer que debería ser preconfigurado por nosotros a un
tiempo no escalable y prefijado, la rapidez, que era lo que se perseguía,
quedaría gravemente mermada.
Así, lo que en un princpio se podría rechazar
por lentitud, como sería la llamada a un alias que se activara en un raw
dependiente de la notificación, por parte del servidor, de la finalización de
envío de los datos que requiramos, resulta ser ahora la manera más precisa y
óptima de codificar.
Éste es un claro y sencillo ejemplo para plasmar que un
código rápido no es siempre la mejor opción, y que la rapidez no lleva consigo,
obligatoriamente, la optimización.
¿Cómo optimizar?
Es posible dividir las líneas
de código compartidas en partes individuales, realizar llamadas dependiendo de
los eventos realizados por el usuario y prever los posibles conflictos o
terminaciones erróneas de las llamadas realizadas.
mIRC nos ofrece amplios
recursos para ello, que no es materia de este artículo explicar, ya que lo
alargaríamos demasiado y no es nuestro objetivo dar clases de programación. Se
supone que quien scriptea seriamente esos recursos ya sabe usarlos.
Con la
optimización se adelanta y se aclaran una serie de errores que pueden darse
habitualmente durante la ejecución de un código, como son:
-la optimización
es una forma eficaz para la detección de bugs
-algunas técnicas de
optimización harán que tu código sea más portable
-tú obtienes más control
sobre tu código
-la optimización hará que tu código sea duro, consistente,
estable y firme
Existen diversas técnicas, todas ellas legítimas y que entran más en el
terreno de los gustos personales y de la manera de cada uno que del propio
resultado final. Mientras el punto de conclusión sea parecido, no debe importar
tanto qué camino o caminos tomamos para ello.
Sin embargo, y sin que sirva
como modelo preferencial, para una visión didáctica del tema pasaré a relatar
por encima el propio estilo que sigo personalmente.
Primeramente, no puedes
dividir tu código y hacerlo más óptimo mientras no tengas claro qué funciones
persisten en él y cuál es su cometido. No puedes tratar de la misma forma todo
ya que tú no tienes potestad sobre el motor de ejecución (hay que recordar que
estás programando para un programa, valga la redundancia, no el programa en sí.
De ahí que se llame scripting).
Yo divido las partes del mIRC y todo lo que
influye en éste en varios campos*1: primeramente, el mIRC no como programa, sino
como generador y soporte, lo que se denomina mIRC engineered scripting (motor de
scripting del mIRC).
A continuación, y sobre ello, se ensambla, lo más
perfectamente posible, el código principal. Es el código con el cual, sin él, el
script no sería script, no funcionaría o, en caso de alterarse, podría funcionar
erróneamente*2. Es lo que denomino "kernel" del script.
En las primeras
actualizaciones el kernel era necesario para actualizar el script. Después ya no
era imprescindible ya que se le puede añadir soporte para actualización. El
motivo de haber retartado esa actualización era la ligereza del código final, y
encontrar un punto medio llevó su tiempo. Hay que tener en cuenta que el kernel
es capaz de trabajar, teóricamente, con cualquier addon medianamente bien
programado.
Tras el kernel se encuentran unos archivos de uso de cara al
programador, es lo que se denomina "modules support & interprety"*3. En
ellos englobaríamos los ini, módulos, etc.
Encima de todos ellos esta el
integrity check, que es la defininición para conjuntar tanto los errores que
pueda captura el mIRC como programa de ejecución, o el propio script. Es
conveniente tener bien claro este concepto.
Como parte final y de nivel más
alto se encuentra lo que denomino "scans and external reads", son archivos de
usuario y engloba todo lo que el usuario puede añadir y hacer. Como se puede
ver, está en el nivel más alejado ya que no lo considero imprescindible, pues su
uso cae en manos del propietario del script. Por poner un ejemplo extremista: yo
no puedo prever que él introduzca código de un troyano.
Repito que ése es un
modelo que me sirve a mí, y está expuesto como materia didáctica. Soy consciente
de que muchos programadores están desarrollando sus propios modelos (otros los
han desarrollado ya) que son tan válidos como éste, o más.
Alto nivel - bajo nivel
Hoy ya se tiene mucho
más claro la frontera que dividen estos dos conceptos, sin embargo, hace apenas
unos años no se entendía y apenas se hacía uso de ellos. Solamente los scripters
más vanguardistas fueron capaces de usarlo.
En palabras llanas, un
programador-scripter que empieza en el mundillo de la programación realizando su
script, o que empieza en el mundillo del scripting haciendo lo propio, sin más
aspavientos ni complicaciones que generar una suerte de archivos capaces de
reaccionar ante determinados eventos realizados por el usuario o el IRC o/y
cualquier otro programa (objetos com dlls, etc.), podría denominarse como un
scripter de alto nivel. Su código no persigue más allá que cumplir una serie de
objetivos puntuales.
Cuando lo que se persigue va más allá, es decir: dotar a
tu script de la capacidad de iteracción, reacción y previsión de conflictos, de
dialogar abiertamente con cualquier ambiente en el que se halle (tomando como
límites, por supuesto, la propia limitación del scripting y del ambiente en el
que se mueve), así como capacitación para incluir addons nativos, estamos
hablando de programación en scripting a bajo nivel.
No es lo mismo, como
algunos erróneamente consideran, entre programar para pics wins o para dlls. Eso
entra más dentro de los gustos personales que de la forma de englobar la
optimización, aunque tanto uno como otro pueda ser más o menos óptimo.
Los objetos de la optimización
Por término
medio, nadie debería:
-Declarar un halt sin previa reconsideración de su
código. Los halt deberían reservarse para eventos planos, tales como capturas de
raw o reacciones verdaderamente irremediables.
-Declarar un bucle sin haber
finalizado e iniciado variables predefinidas. ¿Cuántas veces nos hemos
encontrado con scripts que aprovechan variables? Creo que muchos equivocan el
concepto de reutilización de código con el de reutilización de variable. Gran
pecado, puesto que estos peligros solamente suelen presentarse cuando ya es
demasiado tarde.
En el otro aspecto, la finalización, corre a nuestro favor
que el motor de mIRC posee un buen "recolector" (aunque no sea propiamente eso)
que concluye la variable local. Sin embargo, deberíamos tener siempre en cuenta
en qué estado puede concluir esa variable, no es siempre la manera más óptima la
que se nos ofrece por defecto.
-Declarar variables como locos. Antiguamente
eso se utilizaba mucho. Afortunadamente, hoy cada vez se lleva menos. La
diferencia de una declaración de variables limpia no es tanta la eficiencia del
propio script (muchos suelen argumentar que es lo mismo, puesto que la
diferencia objetivamente entre 100 y 200 variables no es mucha). En la práctica,
una manera tan fea y errónea de programar puede llevar al usuario a que trabaje
con varias variables a la vez, con la consiguiente confusión y el peligro de la
integridad de nuestro código. Las variables deben ser únicas, las genéricas
escasas, reconocibles y, cuanto sea posible, locales.
-Realizar las llamadas
a alias. Para reutilizar código hay que ser extraordinariamente ordenado.
Tú no puedes realizar las llamadas a unos alias de reaprovechamiento si los
tienes desperdigados por todos los códigos remotes. Los buenos scripts catalogan
sus genéricos en sus archivos alias y solamente ponen los locales, o los que van
a usar en el propio archivo remotes.
-Reutilizar código no es reutilizar
salidas. No es buen concepto para la optimización el que aproveches un return
para derivarlo a otro alias. Si un return debe ser procesado, se entiende que
debe ser procesado dentro del propio alias. Partir alias para aprovecharlos
puede llevarte al otro extremo de lo que quieres lograr, es decir: a la
ineficiencia.
Conclusión
Para finalizar, resumiré, en varios puntos, partes que
se deben tener en cuenta, algunas ya expuestas y otras que dejo a la
consideración de tu propia valoración:
-Los recursos de dlls enlentecen. Usa
scripting puro siempre que puedas, aunque también recurras a dll. No lo dejes
todo para las librerías.
-Minimiza grafismos si persigues
rapidez.
-Precalcula límites de hash y de lecturas de buffers.
-Previsiona
salidas de bucles.
-Intenta valorar roturas de código.
-Usa elementos
propios del lenguaje
-Reutiliza los elementos más frecuentes
-Elimina
nombres comunes o denominaciones de dialogs y ventanas populares
-Usa
contadores pequeños
-Usa algorítmica de testeo
-Usa llaves, usa elses para
tratar idéntica entrada, en definitiva: usa una buena metodología de
programación
-Preserva la compatibilidad de tu script con diferentes
versiones
La optimización no es sustituto de la experiencia. Un programador
inexperto puede cometer más errores tratando de optimizar que codificando a la
ligera*4. Pero eso no debe llevar a nadie a la desesperación o el abandono de
buenas prácticas, la optimización debe ir creciendo conforme va creciendo el
aprendizaje.
No es necesario que se sigan estrictas reglas de diversificación
o modelaje de un script, pero sí es imprescindible tener bien claro sobre qué
elementos y lenguaje se trabaja. Esto es esencial.
Tal vez con esta versión
de tu script no logres que sea lo más homogénea y robusta que deseas, pero
seguro que la posterior será mejor. Desde ese punto de vista es desde el cual
debes programar.
*1La división es meramente subjectiva, y se realiza solamente como una idea
conceptual para el posterior tratamiento.
*2Los archivos del corazón del
script no están separados físicamente
*3El modules support & interprety
no son archivos kernel propiedad del programador, sino que son archivos
destinados a cualquier programador. Lo que técnicamente se denominaría como
archivos no propietario.
*4Se entiende que la recursividad virtual añadida al
scripting es materia que deben conocer expertos programadores, un chaval que
empieza a scriptear puede encontrarse al final de todo su empeño con un script
destructivo e inoperante.
©Arphean 2004
Gracias a Nifelheim por repasos y correcciones
Se permite copia y distribución siempre y
cuando se cite la fuente de procedencia y su autor.