lunes, 25 de julio de 2011

Curso de programación: Capítulo 5. DataManager: Como eliminar variables globales


Hola a todos,

A medida que los proyectos se van haciendo grandes una de las primeras cosas que se han de eliminar son las variables globales de archivo ya que rompen totalmente la modularidad y son un peligro para el mantenimiento y la seguridad de nuestra aplicación informática.

Como eliminarlas cuando realmente son necesarias? Hay ocasiones en que las variables globales no son fáciles de eliminar, o que sencillamente la solución es engorrosa y empeora la legibilidad del código (principalmente por el crecimiento del número de parametros en las funciones).

La solución aquí propuesta es la de implementar un DataManager que nos permita asignar tags a variables (por ahora ints) y que nos permita realizar operaciones con estos tags.  De esta manera, nosotros solo tendremos que hacer algo de estilo en cualquier lugar del código para trabajar con una cierta "variable":

if (DataManager::singleton().Get("LEVEL") > 10 || DataManager::singleton().Get("LEVEL") == 0)
            DataManager::singleton().Set("LEVEL",1);
...
DataManager::singleton().Inc("LEVEL");
...
sprintf(cad,"ITEMS:LEVEL%02d",DataManager::singleton().Get("LEVEL"));

Esto nos permite tanto eliminar las variables globales, como tener un sistema de gestión de datos ya preparado para scripts, a la vez que nos permite tener toda la información encapsulada y modular (permitiendonos realizar checkeos y comprovaciones si llegara el caso.)

El código del DataManager propuesto es el siguiente(si teneis nuevas ideas o propuestas no dudeis en hacermelas llegar):

DataManager.h:
/**************************************************************************************************/
// DataManager.h : Código de la parte de gestión de datos del game engine
//    Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/

#ifndef __DataManager__
#define __DataManager__

#define MAX_VARS 256 //Número máximo de variables que permitiremos dentro del data manager

typedef struct
{
    char id[32];
    int val;
}Data;

class DataManager
{
private:
    // Constructor y destructor de la clase
    static DataManager instance;
    DataManager();
    ~DataManager();

public:
    static DataManager& singleton();

public:
    //Funcion para inicializar el motor de sonido
    void Init(int* argc, char* argv[]);

    //Funcion para desinicializar el motor de sonido
    void DeInit();

public:
    void Set( char id[], int val );
    int  Get( char id[] );
    void Inc( char id[] );
    void Dec( char id[] );
    void Swap( char id1[], char id2[]);
    void Move( char id1[], char id2[]);
    void Add( char id1[], char id2[]);
    void Add( char id[], int val);
    void Sub( char id1[], char id2[]);
    void Sub( char id[], int val);

private:
    Data vars[MAX_VARS]; //Vector donde guardamos las variables scripteadas
    int max_vars;         //Número de variables que hay hasta el momento
};

#endif // __DataManager__




DataManager.cpp
/**************************************************************************************************/
// SoundManager.h : Código de la parte de audio del game engine
//    Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/
#include "DataManager.h"
#include "MyGL.h"

#include <iostream>        //Usada para imprimir por consola

using namespace std;

//Instancia única del sound manager
DataManager DataManager::instance;

DataManager::DataManager()
{
}

DataManager::~DataManager()
{
}

//Devolvemos el puntero al singleton
DataManager& DataManager::singleton()
{
    return instance;
}

//Sounds functions
void DataManager::Init(int* argc, char* argv[])
{
    cout << "Inicializamos el data manager\n";
    int i;

    for(i = 0 ; i < MAX_VARS; ++i)
    {
        vars[i].id[0] = '\0';
        vars[i].val = 0;
    }
    max_vars = 0 ;
}

void DataManager::DeInit()
{
    cout << "Desinicializamos el data manager\n";
}


//SET
void DataManager::Set( char id[] , int val )
{
    int i;

    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            vars[i].val = val;
            return;
        }   
    }
   
    //Si no existe esta etiqueta la creamos
    sprintf( vars[max_vars].id ,"%s", id);
    vars[max_vars].val = val;
    max_vars++;

}

//GET
int DataManager::Get(char id[])
{
    int i;
    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            return vars[i].val;
        }   
    } 

    //Este es el único caso para que en el caso de no existir la variable no la creamos
    return 0;
}

//INC
void DataManager::Inc(char id[])
{
    int i;
    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            vars[i].val++;
            return;
        }   
    } 

    //Si no existe esta etiqueta la creamos
    sprintf( vars[max_vars].id ,"%s", id);
    vars[max_vars].val = 1;
    max_vars++;
}

//DEC
void DataManager::Dec(char id[])
{
    int i;
    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            vars[i].val--;
            return;
        }   
    } 

    //Si no existe esta etiqueta la creamos
    sprintf( vars[max_vars].id ,"%s", id);
    vars[max_vars].val = -1;
    max_vars++;
}

//Swap temp = var1; var1 = var2;  var2 = temp;
void DataManager::Swap( char id1[], char id2[])
{
    int i;
    int var1 = -1 , var2 = -1 ;
    int temp;

    for(i = 0 ; i < max_vars; ++i)
    {
        if(var1 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id1 ) )
            {   
                var1 = i;
            }
        }

        if(var2 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id2 ) )
            {   
                var2 = i;
            }
        }

        if(var1 != -1 && var2 != -1)
            break;
    } 

    if(var1 != -1 && var2 != -1)
    {
        temp = vars[var1].val;
        vars[var1].val = vars[var2].val;
        vars[var2].val = temp;
        return;
    }

    if ( var2 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id2);
        vars[max_vars].val = 0 ;
        var2 = max_vars;
        max_vars++;
    }

    if ( var1 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id1);
        vars[max_vars].val = vars[var2].val;
        vars[var2].val = 0;
        max_vars++;
    }
}

//Move var1 = var2; 
void DataManager::Move( char id1[], char id2[])
{
    int i;
    int var1 = -1 , var2 = -1 ;
   
    for(i = 0 ; i < max_vars; ++i)
    {
        if(var1 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id1 ) )
            {   
                var1 = i;
            }
        }

        if(var2 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id2 ) )
            {   
                var2 = i;
            }
        }

        if(var1 != -1 && var2 != -1)
            break;
    } 

    if(var1 != -1 && var2 != -1)
    {
        vars[var1].val = vars[var2].val;
        return;
    }

    if ( var2 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id2);
        vars[max_vars].val = 0 ;
        var2 = max_vars;
        max_vars++;
    }

    if ( var1 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id1);
        vars[max_vars].val = vars[var2].val;
        max_vars++;
    }
}

//ADD var1 = var1 + var2;
void DataManager::Add( char id1[], char id2[])
{
    int i;
    int var1 = -1 , var2 = -1 ;

    for(i = 0 ; i < max_vars; ++i)
    {
        if(var1 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id1 ) )
            {   
                var1 = i;
            }
        }

        if(var2 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id2 ) )
            {   
                var2 = i;
            }
        }

        if(var1 != -1 && var2 != -1)
            break;
    } 

    if(var1 != -1 && var2 != -1)
    {
        vars[var1].val += vars[var2].val;
        return;
    }

    if ( var2 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id2);
        vars[max_vars].val = 0 ;
        var2 = max_vars;
        max_vars++;
    }

    if ( var1 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id1);
        vars[max_vars].val += vars[var2].val;
        max_vars++;
    }
}

void DataManager::Add( char id[], int val)
{
    int i;
    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            vars[i].val+=val;
            return;
        }   
    } 
           
    //Si no existe esta etiqueta la creamos
    sprintf( vars[max_vars].id ,"%s", id);
    vars[max_vars].val = val;
    max_vars++;
}



//SUB var1 = var1 - var2;
void DataManager::Sub( char id1[], char id2[])
{
    int i;
    int var1 = -1 , var2 = -1 ;

    for(i = 0 ; i < max_vars; ++i)
    {
        if(var1 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id1 ) )
            {   
                var1 = i;
            }
        }

        if(var2 == -1)
        {
            //La hemos encontrado!!!
            if(!strcmp( vars[i].id,id2 ) )
            {   
                var2 = i;
            }
        }

        if(var1 != -1 && var2 != -1)
            break;
    } 

    if(var1 != -1 && var2 != -1)
    {
        vars[var1].val -= vars[var2].val;
        return;
    }

    if ( var2 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id2);
        vars[max_vars].val = 0 ;
        var2 = max_vars;
        max_vars++;
    }

    if ( var1 == -1)
    {
        //Si no existe esta etiqueta la creamos
        sprintf( vars[max_vars].id ,"%s", id1);
        vars[max_vars].val -= vars[var2].val;
        max_vars++;
    }
   
}

void DataManager::Sub( char id[], int val)
{
   
    int i;
    for(i = 0 ; i < max_vars; ++i)
    {
        //La hemos encontrado!!!
        if(!strcmp( vars[i].id,id ) )
        {   
            vars[i].val-=val;
            return;
        }   
    } 
       
    //Si no existe esta etiqueta la creamos
    sprintf( vars[max_vars].id ,"%s", id);
    vars[max_vars].val = - val;
    max_vars++;
}

Espero que os haya gustado y que os haya servido

Nos vemos
LordPakusBlog

0 comentarios :

Publicar un comentario

Entradas populares