Raised This Month: $51 Target: $400
 12% 

Métodos de estructuración de código.


  
 
 
Thread Tools Display Modes
Author Message
YakumoHiratsuhi
Veteran Member
Join Date: Dec 2010
Location: Dreαmlαnd.
Old 03-13-2013 , 20:53   Métodos de estructuración de código.
#1

Nota: Sigue en edición, lo publique por error, di un click infalso y lo publique.. pls
Esto más que nada son algunos de mis consejos (en mi opinión) de como estructurar un código para una buena interpretación de este a la hora de compilarlo, pues como sabemos, Pawn es un lenguaje estructurado y al saber como manejar correctamente su flujo de datos, nos podemos ahorrar unos cuantos megas de memoria y unos dolores de cabeza, la estructura de tu código debe tener una manera en el que el código sea leído de una manera rápida y eficiente, considerando todos los métodos de optimización que hayas aprendido hasta ahora y todos los conocimientos que tienes, digamos que es necesario un nivel medio-avanzado de programación para llevar a cabo estos temas.

1. Flujo de datos atravez de condiciones.
Lo más importante en los lenguajes de programación es controlar el flujo de los datos atravez de las sentencias if, estas son muy importantes en su forma de interpretar el código, pero hasta donde sabemos, hacer condiciones sin sentido lo único que crea es que el procesador tarde más en leer la cadena de sentencias y comparar todos sus resultados para ver si debe tomar la ruta de esta sentencia.

Un ejemplo sería:
PHP Code:
    // ESTO ESTA MAL [X]
    // Porque? estas chequeando si esta vivo en una función que solo puede ser llamada cuando
    // el jugador esta vivo, el procesador tarda mas tiempo en leer la sentencia cuando esta usualmente
    // siempre dara true (puede dar false en algunos casos) sin mencionar que debajo de las nativas
    // tambien se esconde un codigo que dependiendo del costo de la operación, puede tener resultados fatales.
    
if(is_user_alive(id) && !(pev(idpev_flags) & FL_ONGROUND) && g_someglobalvariablepls[id])
        
// Algun codigo muuuuy muuuuy largo..
    
    // Otro codigo un poco menos largo que el de arriba..

Esto facilmente se puede arreglar preguntando y/o leyendo el SDK para ver que chequeos y que otras cosas hace una función a la hora de programar tu estructura, para así evitar poner sentencias inutiles.
Otra cosa que tambien puede ser un dolor de cabeza, es la mala estructuración de los anclajes en sentencia, lo que provoca que pueda tirar falsos positivos/negativos.

Ejemplo:
PHP Code:
new g_randomvar[3]
        
g_randomvar[0] = 6
        g_randomvar
[1] = 26
        g_randomvar
[2] = -1

public fw_AlgunaFuncion(identFloat:magnitud[3])
{
    
// Esta función segun nosotros es esta logica.
    // Si g_randomvar[0] es menor a 6 ó g_randomvar[2] es negativo y g_randomvar[1] es mayor a 25
    
if(g_randomvar[0] < || !g_randomvar[2] && g_randomvar[1] > 25)

Aquí, esta función estaría dando resultados erróneos, porque -1 no es un numero que sea interpretado como negativo en este lenguaje, aparte de eso, puede tirar falsos errores el ANDing de la segunda sentencia, para arreglar esto, debemos ajustarnos a sentenciar exactamente lo que que queremos.
PHP Code:
    // Si g_randomvar[0] es menor a 6 ó g_randomvar[2] es negativo (cero) y g_randomvar[1] es mayor a 25
    
if(g_randomvar[0] < || (g_randomvar[2] == && g_randomvar[1] > 25)) 
Ahí estamos interpretando exactamente lo que queremos, entonces no debería de haber problemas a la hora de leer la sentencia.

Nota: Sentencias adjuntas
No se exactamente como se le llama a esto, pero cuando adjuntas varias sentencias en un solo parentesis, estas daran solamente 1 resultado en la misma condición.
Ejemplo:
PHP Code:
new g_randomvar[3]
        
g_randomvar[0] = 0
        g_randomvar
[1] = 1
        g_randomvar
[2] = 0

public fw_AlgunaFuncion(identFloat:magnitud[3])
{
    
// Esta logica dara solamente 2 resultados en el interprete y se lee de esta manera
    // Si g_randomvar[0] es positivo == true
    // si g_randomvar[1] y g_randomvar[2] son positivos == true / de lo contrario si alguno de estos son negativos es false
    
if(g_randomvar[0] || (g_randomvar[1] && g_randomvar[2]))
        
    
// @ Interprete
    
if(true || false)
        
// pls...
    
    
    // Sin anclajes
    
if(g_randomvar[0] || g_randomvar[1] && g_randomvar[2])
        
    
// @ Interprete
    
if(true || false && false// false y false == false.. lol
        // pls...

Estructura de Flujo
Como sabemos, algunas personas diseñan una solución al problema que tienen programando lo que se les vaya saliendo de la mente y irlo desarrollando conforme vayan depurandolo, esto no esta mal, pero nunca ha sido una buena forma de programación, un mejor método de programación, es hacer un diagrama de flujo, donde se pueda ver como funcionara el programa, que rutas tomara en cada caso, que problemas podrían surgir al intentar tomar cada una de las rutas y finalmente como solucionar esos problemas.
Aquí un ejemplo:
PHP Code:
// Alguna función al azar
public fw_EpicFunction()
{
    
// Digamos que segun su estructura, seguira unos cuantos caminos
    
if(/* condicion que siempre tirara true */)
    {
        
// Code pls..
        
        
if(/* Condicion que siempre tirara false*/)
        {
            
// Code pls..
            // ...
            // ....
        
}
        
        
// Un metodo tonto de hacer algo (dense a imaginar que)
        
        
if(/* condicion correctamente usada */)
        {
            
// Code pls..
            // ...
            // ....
        
}
    }

En las funciones que usualmente siempre tiran true/false es suelen ser donde se usan cvars cuyas preferencias siempre quedan en un solo valor, para eso es mejor remover el flujo de condiciones innecesarias y remover el codigo no usado.
--->
PHP Code:
// Alguna función al azar
public fw_EpicFunction()
{
    
/*Suponiendo que borramos un flujo que no es necesario aquí quedaría el codigo de lo que siempre tiraba true */
    
    // Un metodo tonto de hacer algo (dense a imaginar que)
    
    /*Suponiendo que borramos un flujo que no es necesario aquí BORRARIAMOS el codigo de lo que siempre tiraba false */
    
    
if(/* condicion correctamente usada */)
    {
        
// Code pls..
        // ...
        // ....
    
}

Ahí estamos reduciendo su estructura, por ende es mejor pues el procesador lee solamente lo que tiene que leer, a lo que me refiero es que si el flujo de la condición es siempre constante, es mejor borrarlo.

2. Asignación de memoria.
Pros y contras de new y static a petición de Gladius.
new es la forma de declarar una variable en este lenguaje, esta variable segun donde se declare, pasara a ser privada o global, cuando es privada, solamente puede usarse en la funcion donde se declaro y cuando es global puede usarse en cualquier parte, esta cuando es privada, ya no es referenciada y la funcion termina de ejecutarse, es practicamente eliminada de la memoria, cuando es global esta es eliminada de la memoria cuando el mapa se cambia, esta es buena para usarse en funciones que practicamente no se llaman muy seguido, pues la memoria sera liberada al terminar de ejecutar lo que se vaya a hacer, en funciones recursivas tiene un impacto negativo cuando el stack de memoria que declaramos es grande, pues tiene que inicializar cada una de las veces el stack de memoria.

static por su parte, es tambien otra manera de declarar una variable, solo que esta se guarda en memoria y puede cargar los datos aun cuando la funcion no se esta ejecutando, cuando es referenciada, su valor sera el mismo que dejo en la anterior ejecución, esta es una keyword usada para las funciones recursivas, que usualmente requieren estar obteniendo datos, sus pros son que no tiene que ser inicializada, pues una vez creada, reside en memoria y se queda ahi hasta que se cambie el mapa, sus contras es que al crear grandes stacks de memoria, estos se guardan en RAM, dando un impacto negativo en VPS o en PCs de muy bajo rendimiento, pero eso muy poco probable que eso pase.

PHP Code:
// Flujo de variables para dummies (en una función).

// NEW
public func(you_daft_wankerbloody_frog_would_be_more_use_than_you)
{
    
// Inicializa (cada vez que esta funcion sea llamada lo hara).
    
new newtypevar
    
    
// Obtiene datos.
    
get_something(newtypevar)
    
    
// Los manda para algun lado.
    
send_to_somewhere(newtypevar)
    
    
// Se borra.
}

// STATIC
public func(you_daft_wankerbloody_frog_would_be_more_use_than_you)
{
    
// Inicializa.
    
static statictypevar
    
    
// Obtiene datos.
    
get_something(newtypevar)
    
    
// Los manda para algun lado.
    
send_to_somewhere(newtypevar)

Los 2 tienen diferentes usos para lo que se quiere hacer y el error de muchos es asignar memoria que no usan, incrementando el tamaño del plugin y el tiempo en el que el procesador lee cada valor ASCII para interpretarlo como letra (en el caso de cadenas).
Ejemplo:
PHP Code:
// Hook del Mensaje 'SayText' -> register_clcmd("say", "clcmd_sayhook")
// Funcion que se llama cada vez que el usuario escribe algun texto publico.
public clcmd_sayhook(id)
{
    
// Es correcto utilizar static para guardar que dijo en memoria y reemplazarlo cada
    // vez que sea llamada la función.
    
static quedijo[192]
    
read_args(quedijocharsmax(quedijo))
    
    if(
quedijo[0] == '&' || quedijo[0] == '(')
        
// asd..
    
    // asd...

Ahí nuestro error es asignar 192 celdas de memoria cuando solo estamos chequeando 1 sola, esto hace que el procesador tenga que cargar un poco más de datos cuando la variable es referenciada (aunque estos estén en ceros), una solución a esto sería cambiarlo por new (a su gusto y preferencia, pues es un array muy chico) y reducir el tamaño del array a 2, pues ahí estamos gastando exactamente 760 bytes de memoria que podríamos usar en otra operación.

Otro error parecido es que estamos interactuando con alguna cosa que necesita ser chequeada con strings y hacemos esto:
PHP Code:
new const MyString[] = "MyStringTROLOLOL" // <- MyString[17+1] el +1 es por si las dudas.

// llamada 5 veces por segundo..
public fw_SomeRandomFunc()
{
    static 
customstring[64]
    
AlgunaNativaQueObtieneUnString(customstringcharsmax(customstring))
    
    if(
equal(customstringMyString))
        
// pls..
    
    // pls..

No necesariamente algunas cosas necesitan ser chequeadas con strings, hay algunos métodos como utilizar sus valores privados (pev) o incluso darles un id, pero aquí el caso es que estan asignando y chequeando una cadena de 64 caracteres máximos con una que solo tiene 16.. están referenciando memoria innecesaria, mi consejo es que solo usen los caracteres maximos de las cadenas que estan comparando.. si comparan varias cadenas precomputadas, fijense cual es la más grande y establescan ese valor (+1 o +2 celdas para evitar problemas) y así se ahorran unos cuantos kilobytes o incluso megas de memoria.

Otro problemilla puede ser a la hora de hacer menus del viejo estilo, es que tienes que mostrar tu mismo un texto y detectar las teclas presionadas.
PHP Code:
public mostrar_menu_clasico1(id)
{
    static 
menu[1000]
    
// Menu pls..
}

public 
mostrar_menu_clasico2(id)
{
    static 
menu[1000]
    
// Menu pls..
}

public 
mostrar_menu_clasico3(id)
{
    static 
menu[1000]
    
// Menu pls..

Ahí estamos asignando una cantidad enorme y exagerada de memoria.. como formatex no crea un copy-back.. lo más utilizado es usar un lenght para determinar desde donde empieza a escribir nuevos datos (utilizado en ZP), ahí podemos optimizar el codigo creando una sola variable global de 1000 celdas y intercalarla entre todos los menus.
-->
PHP Code:
new g_menu[1000]

public 
mostrar_menu_clasico1(id)
{
    new 
len
    
// Menu pls..
}

public 
mostrar_menu_clasico2(id)
{
    new 
len
    
// Menu pls..
}

public 
mostrar_menu_clasico3(id)
{
    new 
len
    
// Menu pls..

Lo mismo puede ser con otras funciones que hagan lo mismo pero tengan que manejar diferentes textos, ahí simplemente guardan 4kb de memoria en textos y se intercalan entre ellos, siempre y cuando usen el mismo método (el lenght, en este ejemplo), como podría ser un motd (que también puede usar lenght) o un archivo de texto escrito con write_file() tambien usa lenght.

Gracias a stereo por la sugerencia de abajo.
Otro error común es que algunas personas crean un bucle y dentro de el inicializan variables, esto es malo para bucles de gran escala, puesto que cada vez que el bucle se inicia, si se usa new explicado como funciona arriba, tiene el mismo impacto como si fuera una función iterativa (parecida a la recursiva, solo que esta se repite x numero de veces). Cada vez que el bucle se repita, la variable sera creada de nuevo, thus, desgastando al CPU dependiendo del tamaño de las variables, la solución sencilla es declararlas una sola vez FUERA del bucle.

PHP Code:
// Forma asquerosa.
forward func()
{
    while(
false// No quotees esto, no seas el capitan obvio, lo que explico esta abajo v
    
{
        new 
fuckmycpu[400// NOOOOOOOOOOOOOOOO
        
        // ...
    
}
}

// Forma mas o menos
forward func()
{
    new 
softitalil[400]
    
    while(
true// ._.
    
{
        
//...
    
}

3. Estructura teórica
Nota: Esta parte es puro texto aburrido y sin ejemplos, debido a que es una sección individual.
Este probablemente sea el bloque más complicado que habra que repasar, puesto que esto es de cada quien, no quiero que se arme un pedo porque todos tenemos un diferente pensamiento, así que respeten los codigos de otros programadores, por más bonitos o asquerosos que sean.

Cuando tu vas a hacer un plugin, masomenos te das una idea de como lo vas a hacer, que funciones del motor vas a hookear y que vas a hacer con ellas, aquí es donde entra tu estilo, pues cada quien piensa mejor o peor y tiene distintas formas de hacerlo, pero el problema es que lo que queremos es mejorar, entonces que hacemos?

Después de pensar profundamente como va a ser tu plugin tienes entonces ya una parte hecha, la parte teórica, esta viene referenciando a como va a funcionar tu plugin de una manera pensada, sin embargo debemos pensar en todas las cosas posibles que pueden suceder al hacer una cosa, porque como sabemos, generar una respuesta genera muchísimas mas preguntas.

Cuando tengas un plugin teórico este tiene que tener en cuenta los siguientes puntos (avísenme si se me va alguno y NO, no están ordenados)
  • Método que vamos a usar
    Aquí piensas como va a funcionar tu plugin, por ejemplo: Digamos que yo quiero que salte mas alto cuando brinque pero sin ajustar gravedad, voy a hacer esto, esto y eso..
  • Problemas que podría causar el método que vamos a usar
    Es una pre-depuración.. en que podría perjudicar a otros plugins, usando este ejemplo, podría perjudicar al multijump.
  • Funciones, variables y nativas que usaremos
    Suponiendo que usamos lo de arriba, usaremos pev_velocity para establecer una magnitud mas fuerte al salto.
  • Como podríamos optimizar lo que ya tenemos
    Si es que se puede, como se puede mejorar lo que ya esta hecho.
  • Flujo continuo del plugin
    Eliminar las cosas que de plano no usaremos mucho y que afectan la velocidad del plugin por más mínima que sea esta, recuerden que les puede pasar como a mí, que los detalles siempre terminan dándome un cáncer
  • Depuración (este se podría decir que es después de hacer el plugin)
    Arreglar los bugs que se reporten de este ya sea en el mismo juego o en alliedmods, si es que es publico

Una vez que tengamos esto podemos pasar a crear el plugin, pero ojo aquí para eso esta alliedmodders, para cuando tu no puedas pensar por tu cuenta alguno de los siguientes puntos, todos los de la comunidad puedan ayudarte ya sea cuando estés haciéndolo o cuando todavía este en esta fase..

4. Reducción de instrucciones
Cuando ya tienes un codigo más o menos limpio, otra forma de reestructurarlo para que este sea más fluido es intentando reducir las lineas de codigo por argumentos sencillos y menos lineas de codigo, así los lectores del codigo fuente se estresan menos.

Un ejemplo sería a la hora de emplear strings, tenemos una variable que decidira lo que se mostrara en pantalla, pero tipicamente muchas personas usarian un if, cuando realmente es cuestion de utilizar una sentencia pegada a la nativa que llamaremos.

PHP Code:
// Dummy way
public somerandomjunk(idive_meet_smarter_donkeys_than_you_lot)
{
    new 
derP
    
    
// Junky code..
    
    
if(derP == 2)
        
client_print(idprint_center"What a plonker!")
    else if (
derP == 5)
        
client_print(idprint_center"I've meet smarter donkeys than you lot!"// lol taba sola
    
else
        
client_print(idprint_center"You daft wanker!")

Esto se puede reducir a una simple linea, un poco larga pero más sencilla de leer.

PHP Code:
public somerandomjunk(idive_meet_smarter_donkeys_than_you_lot)
{
    new 
derP
   
    
// Junky code..
    
    
client_print(idclient_print"%s"derP == "I've meet smarter donkeys than you lot!" derP == "What a plonker!" "You daft wanker!")

Con esto reducimos lineas y ahorramos un poco de lectura, en optimización no influye mucho, pero es más para que sea un buen habito.

Siempre hay que tratar de que las instrucciones sean las menores posibles y que obtengan el resultado que quieres.

Ay luego le sigo añadiendo cosas.. se aceptan comentarios y diganme si les gustan mis consejos y en que se pueden mejorar.
__________________
"Podra parecer ridiculo o imposible, pero este es el camino que seguimos los verdaderos hombres, si hay un muro en el camino, lo derribamos, si no hay camino, haremos uno, con nuestras propias manos, porque el magma de nuestro corazón arde en llamas."

Last edited by YakumoHiratsuhi; 06-03-2013 at 16:34. Reason: taipo
YakumoHiratsuhi is offline
Send a message via MSN to YakumoHiratsuhi
StrikerV2
Senior Member
Join Date: Nov 2012
Location: Chile , O Yes!
Old 03-13-2013 , 21:59   Re: Métodos de estructuración de código.
#2

Muy bueno ! .

No sabia aserca del RegisterHam(Ham_Player_Jump, "player", "fw_Ham_PlayerJump")
nunca lo habia visto, lo usare para algo que se me ocurrio en mi modo strike
__________________
Mi firma era tan sexy .-.

Last edited by StrikerV2; 03-13-2013 at 21:59.
StrikerV2 is offline
Send a message via MSN to StrikerV2
Sidix
Senior Member
Join Date: Feb 2011
Location: Limbo City
Old 03-14-2013 , 00:02   Re: Métodos de estructuración de código.
#3

Excelente...
__________________
[IMG]http://img839.**************/img839/1879/dmcdanteprofile.png[/IMG]
Sidix is offline
rak
Veteran Member
Join Date: Oct 2011
Location: banned country
Old 03-14-2013 , 10:03   Re: Métodos de estructuración de código.
#4

Quote:
Originally Posted by YakumoHiratsuhi View Post
Ejemplo:
PHP Code:
// Hook del Mensaje 'SayText' -> register_clcmd("say", "clcmd_sayhook")
// Funcion que se llama cada vez que el usuario escribe algun texto publico.
public clcmd_sayhook(id)
{
    
// Es correcto utilizar static para guardar que dijo en memoria y reemplazarlo cada
    // vez que sea llamada la función.
    
static quedijo[192]
    
read_args(quedijocharsmax(quedijo))
    
    if(
quedijo[0] == '&' || quedijo[0] == '(')
        
// asd..
    
    // asd...

te falto el remove_quotes por q la celda 0 contiene "

buen aporte
__________________

www.amxmodx-es.com

Steam: Luchokoldo

Last edited by rak; 03-14-2013 at 10:05.
rak is offline
Send a message via MSN to rak Send a message via Skype™ to rak
Bernii
BANNED
Join Date: Feb 2013
Location: Weed Land *-*
Old 03-14-2013 , 11:44   Re: Métodos de estructuración de código.
#5

Buen tuto +10
Bernii is offline
gladius
Veteran Member
Join Date: Jul 2008
Location: Santiago, Chile
Old 03-14-2013 , 12:48   Re: Métodos de estructuración de código.
#6

Pro y con de new y static?
Mejores ejemplos y mas explicacion
Mas explicacion informativa del tema
__________________
Proyects
Kreedz Chile Mod [100%] (Fixing some details).

gladius is offline
Send a message via MSN to gladius Send a message via Skype™ to gladius
Roccoxx
AlliedModders Donor
Join Date: Jan 2012
Location: Argentina
Old 03-14-2013 , 14:59   Re: Métodos de estructuración de código.
#7

buen tuto, siguelo e.e
__________________
Tutorials here (Spanish)

Like as another Pijudo said: "Tired and retired"
Roccoxx is offline
Send a message via MSN to Roccoxx
YakumoHiratsuhi
Veteran Member
Join Date: Dec 2010
Location: Dreαmlαnd.
Old 03-14-2013 , 15:39   Re: Métodos de estructuración de código.
#8

@Rak: Gracias por la aclaración, alrato se lo añado.
@gladius: Trato de que sea breve y que solo recordar lo que ya saben, pero que sepan como emplearlo, por eso es necesario que sepan programación media-avanzada.

Cabe recordarles que no es un tutorial, son consejos, mucha gente hace tonterías que entorpecen el flujo correcto de datos con chequeos inútiles y otros detalles que pueden costarles mucho o poco.
__________________
"Podra parecer ridiculo o imposible, pero este es el camino que seguimos los verdaderos hombres, si hay un muro en el camino, lo derribamos, si no hay camino, haremos uno, con nuestras propias manos, porque el magma de nuestro corazón arde en llamas."

Last edited by YakumoHiratsuhi; 03-14-2013 at 15:45.
YakumoHiratsuhi is offline
Send a message via MSN to YakumoHiratsuhi
rak
Veteran Member
Join Date: Oct 2011
Location: banned country
Old 03-14-2013 , 17:29   Re: Métodos de estructuración de código.
#9

Quote:
Originally Posted by YakumoHiratsuhi View Post
@Rak: Gracias por la aclaración, alrato se lo añado.
o solo pone
PHP Code:
quedijo[1
y lesto e.e una native menos e.e
__________________

www.amxmodx-es.com

Steam: Luchokoldo
rak is offline
Send a message via MSN to rak Send a message via Skype™ to rak
Old 03-14-2013, 17:50
BlackFur
This message has been deleted by lucas_7_94.
baneado
Veteran Member
Join Date: Dec 2012
Location: amxmodx-es.com
Old 03-15-2013 , 05:11   Re: Métodos de estructuración de código.
#10

una pregunta, en un task con retardo de 3 seg hace falta chequear luego si está conectado?

y una duda del zp en los menús, por qué chequea si está conectado en todos los menús, es necesario?
baneado is offline
 



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 16:40.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode