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
Para cualquier contacto:
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.
Datos del autor y datos de interés:
-Arphean (Manuel
González) es informático y programador desde 1996.
En torno al
año 2000 comenzó a programar en scripting
distribuyendo gratuitamente el h@ckScripT a todos los usuarios
del mIRC que lo desearan. Actualmente dispone de su web en:
www.arphean.mirrorz.com
-Los usuarios del h@ckScripT disponen también de una web
específica, construida por los fans y seguidores del
script, que está alojada en www.hackup.cjb.net
-Arphean posee varios trabajos publicados en torno al mIRC
Scripting, así como a determinadas áreas de la
informática. Asimismo, es colaborador del
Departamento de Informática y Sociedad en la
Escuela de
Ingeniería Informática de la
Universidad
Abierta bajo licencia GNU.
-El presente archivo es un trabajo 100%
original, fruto de la experiencia propia y de la
interrelación con diferentes usuarios, programadores y
testers de scripts.
-El título y la categoría se englobarían en
Computación/Internet