lunes, 24 de septiembre de 2012

Lo que extraño de C++


Hola:
         Hoy quiero comentarles algunos choques que tuve cuando me enfrenté a C# viniendo del mundo C++, las cosas que extraño, aunque reconozco que no son muchas, ya que C# realmente tiene innumerables beneficios y por eso hoy es mi lenguaje favorito (no sé mañana).
       
Extraño de C++:

- Las STL: Significan Standar Template Library y traen un conjunto de clases realmente útiles. Tiene una serie de contenedores y los que mas he usado han sido la clase vector (que es como un array pero con métodos que te simplifican la vida), list y deque, sobre todo el deque, ya que este internamente funciona como un list, pero con la sintaxis de un vector, es decir, no necesita iteradores para recorrerse como el list y por lo tanto su sintaxis es menos tediosa. Por qué esto es importante, porque un vector ocupa siempre un bloque de memoria contiguo, es decir que si no hay un bloque de memoria contiguo, se producirían errores, un fallo de memoria o el sistema alertaría de que no hay memoria, es difícil que ocurra hoy con las máquinas que existen, pero pensemos en grandes volúmenes de datos que extraemos de una base de datos y queremos colocarlos en una grilla, si falta memoria, se produce un error, ahí es donde entran en juego los list y los deque, los mismos buscan los lugares vacíos que no necesariamente tienen que ser contiguos. Lo mas parecido a las STL son las Generics de C# en donde la mas usada es la clase List, pero extraño las STL porque hice muchos trabajos con las mismas y por ende les había agarrado la mano. Iguál las Generics no sólo las reemplazan, sino que mejoran en muchos aspectos.

- Tirar una "funcioncita" al aire: Cuando tengo que hacer un método de una clase que a su vez debería usar en varias clases, es ahí donde digo "volvé C++" (hasta que lo pienso mejor) porque en C# o debo hacer una clase especialmente e instanciarla luego o debo crear una Interfaz que contengan su definición y heredar en la clase la misma o bien hacer un método en cada clase que haga lo mismo. Siempre preferí tener una función que haga tal cosa y tenerla en un archivo .h que coloco como cabecera y poder llamarla desde cualquier recóndito rincón de código sin muchos tapujos. Yo sé que los programadores orientados a objetos extremistas me van a pegar el grito en el cielo debido a que va en contra del nuevo orden mundial de programación, pero yo prefiero no ser "extremista" cuando los tiempos te comen, en estos casos se necesita ser "simplista".

- La herencia múltiple: Como todos saben tanto Java y C# no permiten herencia múltiple, sí permiten herencia simple entre clases y múltiples herencias desde Interfaces. Podrán decir que se reemplaza la herencia múltiple con herencias de herencias, es decir un nieto, puede acceder a su padre y su padre a su padre, entonces el nieto puede acceder a su abuelo también, pero en C++ uno heredaba desde donde quería, lo que quería. Es cierto que si existían dos métodos entre las clases que se heredaban que eran iguales, traía inconvenientes, pero si se sabía usar era muy pero muy útil.

- Las etiquetas public, private y protected: Cuando uno creaba métodos en las clases o atributos uno simplemente hacía:
public:
void funcion();
void talcosa();
int a;
private:
int b;
void talotra();

y de esta manera lo que estaba debajo de cada etiqueta era o private o public, en cambio en C# hay que colocarle qué nivel de privacidad va a tener a cada uno de los atributos y métodos:


public void funcion(){}
public void talcosa(){}
public int a;
private int b;
private void talotra(){}


Seguiré modificando este post para ir agregando cosas que extraño de C++, igualmente repito que son muchos más los beneficios que dá C# y que contaré en un post siguiente...


Instalación de PostgreSQL en forma desatendida desde C#

  Hola:
  Este va a ser el primer post de una serie de post para PostgreSql con c#.
  En esta oportunidad me voy a centrar en la instalación desatendida y en algunos
inconvenientes que han surgido y que supe superar.
  En los sucesivos post, explicaré cómo conectar,crear una base de datos y tablas desde C#
con PostgreSQL, debido a que vi muy poco material sobre esto ya que la mayoría te enseña a
conectar PostgreSQL con C# y te dicen que hagas las tablas en pgAdmin o desde la línea de
comandos, esto estaría bien si fuese yo solamente quien va a usar la aplicación o si
nosotros vamos a instalarle al cliente el sistema, pero si queremos hacer una aplicación
para distribuir en masa, no le vamos a pedir a nuestro cliente que haga ese trabajo que debería
hacer nuestra aplicación sin la menor intervención de él, sería como que me vendieran un
auto nuevo y me pidan que yo me encargue de armar el motor.
  Me adelanto a que seguramente van a surgir muchos que ofrezcan mejores soluciones, serán
bienvenidas por supuesto, yo lo que voy a escribir es algo probado por mi, espero que
quienes sugieran otra cosa, den prueba de que lo de ellos ha funcionado.
  Cuando uno hace un instalador, puede empaquetar el .exe instalador del motor de la bd, y
ejecutarlo en el mismo instalador de la aplicación, siguiendo la misma línea de comando que
voy a usar para C#, será cuestión de gustos. A mi me gusta preguntar desde C# si será una
instalación que hará de Cliente o que hará de Servidor. La diferencia es que si es Cliente
no necesariamente hay que instalar PostgreSQL, solamente hay que instalar su conector.
  Algún que otro experto en instaladores podrá saltar y decir muchas cosas que darán por
hecho, pero yo prefiero ser experto en C# y no tanto en instaladores.


Detalles y discusiones previas:

  La versión de PostgreSQL que voy a usar es la 9.2 y se la puede descargar desde esta
dirección: http://www.enterprisedb.com/products-services-training/pgdownload#windows
Allí eligen la mas común que es la versión para Win x86-32, obvio que si tienen un Windows
de 64 bits, deben elegir la otra opción.
Esta versión posee un instalador distinto a la de la versión 8.3 que era un instalador msi
y cuyas opciones de instalación son otras a las que se presentan a partir de la versión
8.4. Les recomiendo que usen la misma versión que yo, porque si les surgen inconvenientes
al menos se descartará que sea por culpa de una versión diferente.
  Una vez descargado, pueden probar si quieren instalarla en forma normal para ir viendo las
opciones, este post sólo tiene el objetivo de instalar en forma desatendida.
En algunos windows de algunas máquinas (sobre todo en windows machacados, de esos que hay
que reinstalar urgentemente) al instalar en forma normal, tiraba algunos errores y no se
terminaba instalando PostgreSQL, estos errores eran con el instalador de EnterpriseDB, no
había dramas con los instaladores msi para la versión 8.3, quizás en esos windows
machacados faltaba algún archivo o algo pasaba que realmente desconozco, pero al instalar
en forma desatendida, se instalaba perfectamente.
  Usaré además el excelente IDE SharpDevelop 4.2.

Instalando desde la línea de comandos:
  Antes que nada les muestro como sería instalar desde la línea de comandos de windows.

A continuación les presento las opciones de instalación que existen en
PostgreSQL 9.2:

--help                         Display the list of valid options
--version                      Display product information
 --unattendedmodeui <unattendedmodeui> Unattended Mode UI
                                Default: minimal
                                Allowed: none minimal minimalWithDialogs
 --optionfile <optionfile>      Installation option file
                                Default: 
 --debuglevel <debuglevel>      Debug information level of verbosity
                                Default: 2
                                Allowed: 0 1 2 3 4
 --mode <mode>                  Installation mode
                                Default: qt
                                Allowed: qt win32 unattended
 --debugtrace <debugtrace>      Debug filename
                                Default: 
 --installer-language <installer-language> Language selection
                                Default: en
                                Allowed: en es fr
 --extract-only <extract-only>  
                                Default: 0
 --superaccount <superaccount>  Sets the user name of the database superuser. Defaults to 
'postgres'.
                                Default: postgres
 --servicename <servicename>    Sets the name of the database service.
                                Default: 
 --serviceaccount <serviceaccount> Sets the operating system user account that owns the 
server process. Defaults to 'postgres'.
                                Default: 
 --servicepassword <servicepassword> Sets the password for the operating system user 
account that owns server process. Defaults to superuser password.
                                Default: 
 --install_runtimes <install_runtimes> Specifies whether or not install the Microsoft 
Visual C++ runtimes before the installation proceeds.
                                Default: 1
 --create_shortcuts <create_shortcuts> Specifies whether or not menu shortcuts should be 
created.
                                Default: 1
 --prefix <prefix>              Installation Directory
                                Default: C:\Archivos de programa\PostgreSQL\9.2
 --datadir <datadir>            Data Directory
                                Default: C:\Archivos de programa\PostgreSQL\9.2\data
 --superpassword <superpassword> Password
                                Default: 
 --serverport <serverport>      Port
                                Default: 5432
 --locale <locale>              Locale
                                Default: 

  Desde la linea de comandos se instalaría de la siguiente manera suponiendo que al archivo
instalador le dejé el mismo nombre con el que se descarga y el mismo se encuentra en el directorio raíz de windows:
C:\>postgresql-9.2.0-1-windows.exe --mode unattended --superpassword mipass  
--servicepassword mipass --serverport 5434 --unattendedmodeui none  --prefix 
C:\PostgreSQL\9.2 --datadir C:\PostgreSQL\9.2\Data
     
--mode unattended: Significa que será en modo desatendido.
--prefix C:\PostgreSQL\9.2: Significa que voy a instalar la base de datos en el directorio
C:\PostgreSQL\9.2, es decir que cambio el que viene por defecto  que es C:\Archivos de
programa\PostgreSQL\9.2\data.
--datadir C:\PostgreSQL\9.2\Data: Instalo los datos en el directorio C:\PostgreSQL\9.2\data en
lugar del que viene por defecto que es C:\Archivos de programa\PostgreSQL\9.2\data.
--serverport 5434: Uso el puerto 5434 y no el que viene por defecto que es el 5432 (si quieren dejen el por defecto que es l que se usa mas comunmente).
--unattendedmodeui none: Le digo que no muestre ni siquiera la ventana mínima.
--superpassword mipass: Establece el password que en este caso será "mipass". Si no colocan esto el pass por defecto será "postgres".

  También puede colocarse otras opciones como --install_runtimes en donde colocando 0 se le
dice que no instale los runtime  visual c++ que necesita para funcionar, pero lo conveniente es
dejar lo que viene por default, osea 1, por si la máquina en que se va a instalar no lo
posee.


Instalando desde C#:
  Primero creo una clase, esta clase se va a llamar InstalacionPostgreSQL y va a tener dos métodos, uno que se va a llamar "Instalar" y va a devolver un bool y el otro se va a llamar "ComprobarSiExiste" que va a devolver un booleano que si es true significa que existe, sino, no existe, este método lo que hace es buscar la clave del registro de PostgreSQL.
  El ejecutable de la instalación de PostgreSQL en esta oportunidad va a estar dentro de la carpeta Installers que vamos a tener dentro de la carpeta donde se encuentra el ejecutable de nuestra aplicación en C#.
  Es recomendable colocar una barra de progreso en una ventanita cosa de mostrarle al cliente que se está instalando algo, debido a que tarda un poco y el cliente puede pensar que la máquina se tildó o algo por el estilo.
 A continuación la clase instaladora:

//Dos espacios de nombres que se van a usar, uno sirve para ejecutar procesos y el otro
//para leer claves en el registro
using System.Diagnostics;
using Microsoft.Win32;

public class InstalacionPostgreSQL  //Nombre de la clase
 {
public InstalacionPostgreSQL() //Constructor sin parámetros
{}
public bool Instalar()  //Función que instala PostgreSQL
{
//Paso al string la ruta del ejecutable de nuestra aplicación
string ruta=Application.StartupPath;
//Le paso que el directorio por defecto sea el del ejecutable
Directory.SetCurrentDirectory(ruta);

//En los siguientes strings indico los parámetros y qué archivo se ejecuta
string installerpostgre=@"--mode unattended --superpassword mypass  --servicepassword mypass --serverport 5434 --unattendedmodeui none  --prefix C:\PostgreSQL\9.2 --datadir C:\PostgreSQL\9.2\Data";
string x="Installers\\postgresql-9.2.0-1-windows.exe";

Process oProc = new Process();//Creo el proceso
try //Con este try catch atrapo cualquier excepción que se produzca
{
oProc.StartInfo.RedirectStandardInput = true;
oProc.StartInfo.RedirectStandardOutput = true;
oProc.StartInfo.CreateNoWindow=true;//Le indico que no debe abrir la típica ventana DOS cuando           ejecuto el proceso
oProc.StartInfo.UseShellExecute = false;
oProc.StartInfo.FileName = x;//Le indico que debe ejecutar el archivo del path que se encuentra en este string
oProc.StartInfo.Arguments = installerpostgre;//Le paso los parámetros que contiene este string
oProc.Start();//Comenzar el proceso
oProc.WaitForExit();//Esperar a que termine el proceso para terminar
oProc.Close();//Cierro el proceso
}
catch{
return false;//Si hubo error, retorno false 
}

MessageBox.Show("Se ha instalado PostgreSQL 9.2.");//Aviso que se instaló correctamente

return true;//Retorno true para que se sepa que se instaló correctamente
}

bool   ComprobarSiExiste()
{
string clavreg=@"SOFTWARE\PostgreSQL\Installations\postgresql-9.2";
 // Abrimos la clave del registro con la que queremos trabajar
RegistryKey rk1 = Registry.LocalMachine;
// Nos movemos hasta la subclave donde queremos trabajar.
// El parámetro boleano indica si la abrimos en solo lectura (false)
// ó en lectura/escritura (true).
rk1 = rk1.OpenSubKey(@clavreg,true);
// Si devuelve null es que la clave no existe
if (rk1 == null)
   return  false; //No existe entonces retorno falso
else
return  true;//Existe entonces retorno verdadero
}

}//Fin de la clase


                       Errores con los que me topé:

  Asegúrensen de tener el editor del código de SharpDevelop en fuente tipo Unicode como puede ser Arial Unicode MS porque puede mal interpretar los dos guiones seguidos "--" y a uno interpretarlo como otro carácter, es por eso que si le aparece un cartelito que les indica en inglés que se fije en la ayuda del instalador, prueben cambiar la fuente del editor yendo a Herramientas-Opciones-Editor de Texto de SharpDevelop y allí cambiar dicha fuente. Ahora lo cuento como algo sencillo pero estuve bastante para saber que era eso tan simple.
  Investigando en instalaciones de PostgreSQL 9.2 me he topado con que muchos en lugar de
colocar --serverport, colocan --port o mas adelante cuando se vea creación de base de datos PostgreSQL 9.2 y creación de tablas, para realizar la conexión colocan --server en lugar de --host, esto tiene como resultado que no se instala PostgreSQL 9.2 ni se crea ni la base de datos y por supuesto, tampoco las tablas. Ojo! en la "Conexión" a PostgreSQL 9.2 una vez instalada ésta, sí hay que usar --port en vez de --serverport, ignoro por qué lo hicieron así, pero en la "Instalación Desatendida" es al revés. Otro es que en lugar de --superpassword vi post que colocan --user o --user id, esto tampoco sirve, no se instala y en el caso de la creación de base de datos y tablas, tampoco sirve, porque ahora se usa --username.


                              Ejemplo de Aplicación:

  Supongamos que ya tenemos los formularios o una ventana WPF de una Agenda que va a Funcionar con PostgreSQL (Es un desperdicio usar PosgreSQL para una agenda, convendría usar algo como SQLite, pero aquí es a modo de ejemplo).
  Usando la clase InstalacionPostgreSQL podríamos hacer algo así:

public partial class Agenda : Window
{
#region {Globals Variables}
InstalacionPostgreSQL InPostgre=new  InstalacionPostgreSQL ();  //Creo un objeto de la clase
#endregion {Globals Variables}

#region {Constructor}
public Agenda()
{
InitializeComponent();//Cargo los componentes de la agenda, que puede ser una Datagrid o cualquier //elemento que uno haya colocado en el WPF

if(!InPostgre.ComprobarSiExiste()) //Pregunto si no existe PotgreSQL
{
//Si no existe instalo
InPostgre.Instalar();

}
}
#endegion {Constructor}
 }//Fin clase





martes, 18 de septiembre de 2012

Bienvenidos!!!

 Bienvenidos a todos al mundo C#!!!
 Este blog tiene el objetivo de compartir experiencias y anécdotas para guiar en algunos problemas particulares con los que me he enfrentado en este mundo apasionante de la programación de este gran lenguaje.