¿Programo bien?

30/01/2007 - 21:08 por alberto | Informe spam
Menuda pregunta, no??

Os quiero contar brevemente cómo planteo el desarrollo de los proyectos
sencillos:

1) Trabajo con SQL Server y todas las instrucciones sql las almaceno como
procedimientos almacenados.
2) Tengo una biblioteca que contiene una clase que me da acceso a la base de
datos. En esta clase tengo métodos que me dejan ejecutar instrucciones tipo
Insert, Delete, etc. (vamos, las ExecuteNonQuery del objeto command),
métodos para obtener un escalar, etc.
Si, por ejemplo, quiero obtener un DataReader con ciertos datos, solo
tengo que hacer lo siguiente: SqlDataReader dr =
bd.ObtenerDatos(nombreProcedimientoAlmacenado);
3) Tengo otra capa con los objetos de mi negocio (Clientes, facturas,
productos, etc) que es la que realmente se comunica con la capa de acceso a
datos.
4) Finalmente, el interface solo se ocupa de trabajar con objetos de la capa
de negocio. Si, por ejemplo, quiero grabar un cliente, haré algo parecido a
lo siguiente:
miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

¿Considerais que es un modo correcto de afrontar el desarrollo de una
aplicación?
Muchísimas gracias por vuestra opinión.

Preguntas similare

Leer las respuestas

#16 Alfredo Novoa
31/01/2007 - 18:51 | Informe spam
On 31 Jan 2007 08:36:13 -0800, "Roberto M. Oliva"
wrote:

>Yo solo te recomendaria incluir TDD (Test Driven Development). Es una
>metodologia de testeos de clases. Con ella testeas toda la capa de
>negocios.

Si el objetivo es maximizar el coste de desarrollo entonces está muy
bien. Por supuesto también habría que crear clases para testear las
clases de testeo, y así sucesivamente.




Se ve que no sabes de que estoy hablando



Lo se perfectamente. El TDD es la enésima moda estúpida dentro del
mundo de los objetos.

Los tests de regresión son más viejos que el hambre.

http://en.wikipedia.org/wiki/Regression_testing

El software hay que probarlo usando el sentido común. Crear un
procedimiento de test por cada procedimiento del programa como si
fueses un robot es estúpido, y es justo lo que promueven muchas
herramientas TDD.

Crear sistemáticamente un módulo de test por cada módulo de programa
también puede ser estúpido en muchos casos. En muchos casos un pequeño
conjunto de pruebas de alto nivel puede probar montones de módulos a
la vez con mucho menos esfuerzo.

Crear los tests antes que el programa a veces puede tener sentido y
otras muchas veces puede ser estúpido, como por ejemplo si quieres
probar una interfaz gráfica de usuario.

Escribir código para que falle los tests a propósito es otra tontería.

Y luego está el problema de como saber que los tests son correctos.

En resumen, las recetas simplonas para no tener que pensar no dan
buenos resultados. Siempre hay que usar el sentido común.


Saludos
Respuesta Responder a este mensaje
#17 Alberto
31/01/2007 - 19:08 | Informe spam
Otra de las ventajas de usar SP es que ciertas modificaciones son
transparentes al usuario. No es necesario volver a compilar la aplicación y
volverla a instalar.

"Alfredo Novoa" escribió en el mensaje
news:
On Wed, 31 Jan 2007 08:17:47 -0400, "Carlos"
wrote:

Y meter sistematicamente las consultas dentro de procedimientos
almacenados es otro absurdo.




Significa que conviene usar los SP's principalmente para acciones de
actualización ?



No, lo que conviene es no usar los SP. La mayoría de los SP que se
necesitan son triggers y también conviene usarlos lo menos posible.

Ahora mismo estamos pasando una aplicación vieja de DBase a SQL Server
y gracias a las vistas indexadas apenas estamos necesitando triggers
ni SP.

Estamos eliminando un montón de código de la aplicación que no se
convierte en código de servidor. Simplemente ya no es necesario
gracias al mayor nivel de abstracción de la programación declarativa.

y que las consultas deberían enviarse directamente desde
la aplicación? No "amarraría" esto más a la aplicación con el SGBD?



No. ¿Que diferencia hay entre "amarrarse" a tablas que a SP?

Lo que si hay que hacer es aprovechar el sistema de permisos, las
vistas, los alias, etc.

Considerando la ventaja de pre-compilación que aportan los SP's, no
convendría también tener las consultas más complejas/frecuentes en SP's?



Hay más formas de precompilar como por ejemplo vistas y preparación de
consultas. Además el tiempo de compilación no suele ser muy
significativo. Si reduces el tiempo de una consulta en 50 milisegundos
nadie te lo va a agradecer.

ok. Eso lo tengo claro. Las reglas de integridad de los datos y de sus
datos derivados deben ser responsabilidad unica y exclusiva del SGBD ya
que
eso independiza los datos y su integridad, de la aplicación.



Exacto, y además le estamos danto oportunidades al optimizador para
hacer su trabajo.

2) La interfaz se ocupa de presentar los objetos de la base de datos a
los usuarios, comunicandose con el SGBD a través del lenguaje SQL.



Ok pero siguiendo el mismo ejemplo, aunque entendemos que es muy trivial,
de
que otra manera se pueden "presentar los objetos" en la interfaz si no es
de
forma parecida a la que propone el compañero?



Con datasets, y datatables.

es decir mapeando la entidad
cliente como una clase (objeto) en la aplicación.



No se puede mapear una tabla con una clase por que es absurdo, lo que
se hace es mapear una tabla con un objeto de tipo colección.

Tienes otra alternativa
para eso mismo, o ejemplo?



Un datatable directamente conectado por DataBindings a los controles
visuales.

No tiene ningún sentido hacer algo como esto:

miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

Cuando se usan "databindings"

nota:Disculpa la insistencia, es que me interesa profundizar en este tema
con fines de aclarar conceptos que tengo un poco confusos.



No hay nada que disculpar. Pregunta lo que quieras que yo responderé
lo que me de la gana :-)


Saludos
Alfredo
Respuesta Responder a este mensaje
#18 Alberto
31/01/2007 - 19:13 | Informe spam
No tiene ningún sentido hacer algo como esto:

miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();



El dataBinding está muy bien pero tal y como lo hago yo tienes independencia
de la capa de presentación. Hecha la capa de negocio, hacer un interface
para windows o web me supone poco esfuerzo...y por no hablar de la extrema
claridad del código.

"Alfredo Novoa" escribió en el mensaje
news:
On Wed, 31 Jan 2007 08:17:47 -0400, "Carlos"
wrote:

Y meter sistematicamente las consultas dentro de procedimientos
almacenados es otro absurdo.




Significa que conviene usar los SP's principalmente para acciones de
actualización ?



No, lo que conviene es no usar los SP. La mayoría de los SP que se
necesitan son triggers y también conviene usarlos lo menos posible.

Ahora mismo estamos pasando una aplicación vieja de DBase a SQL Server
y gracias a las vistas indexadas apenas estamos necesitando triggers
ni SP.

Estamos eliminando un montón de código de la aplicación que no se
convierte en código de servidor. Simplemente ya no es necesario
gracias al mayor nivel de abstracción de la programación declarativa.

y que las consultas deberían enviarse directamente desde
la aplicación? No "amarraría" esto más a la aplicación con el SGBD?



No. ¿Que diferencia hay entre "amarrarse" a tablas que a SP?

Lo que si hay que hacer es aprovechar el sistema de permisos, las
vistas, los alias, etc.

Considerando la ventaja de pre-compilación que aportan los SP's, no
convendría también tener las consultas más complejas/frecuentes en SP's?



Hay más formas de precompilar como por ejemplo vistas y preparación de
consultas. Además el tiempo de compilación no suele ser muy
significativo. Si reduces el tiempo de una consulta en 50 milisegundos
nadie te lo va a agradecer.

ok. Eso lo tengo claro. Las reglas de integridad de los datos y de sus
datos derivados deben ser responsabilidad unica y exclusiva del SGBD ya
que
eso independiza los datos y su integridad, de la aplicación.



Exacto, y además le estamos danto oportunidades al optimizador para
hacer su trabajo.

2) La interfaz se ocupa de presentar los objetos de la base de datos a
los usuarios, comunicandose con el SGBD a través del lenguaje SQL.



Ok pero siguiendo el mismo ejemplo, aunque entendemos que es muy trivial,
de
que otra manera se pueden "presentar los objetos" en la interfaz si no es
de
forma parecida a la que propone el compañero?



Con datasets, y datatables.

es decir mapeando la entidad
cliente como una clase (objeto) en la aplicación.



No se puede mapear una tabla con una clase por que es absurdo, lo que
se hace es mapear una tabla con un objeto de tipo colección.

Tienes otra alternativa
para eso mismo, o ejemplo?



Un datatable directamente conectado por DataBindings a los controles
visuales.

No tiene ningún sentido hacer algo como esto:

miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

Cuando se usan "databindings"

nota:Disculpa la insistencia, es que me interesa profundizar en este tema
con fines de aclarar conceptos que tengo un poco confusos.



No hay nada que disculpar. Pregunta lo que quieras que yo responderé
lo que me de la gana :-)


Saludos
Alfredo
Respuesta Responder a este mensaje
#19 Paco Ferre
31/01/2007 - 19:36 | Informe spam
On 30 ene, 21:08, "alberto" wrote:
Menuda pregunta, no??

Os quiero contar brevemente cómo planteo el desarrollo de los proyectos
sencillos:

1) Trabajo con SQL Server y todas las instrucciones sql las almaceno como
procedimientos almacenados.
2) Tengo una biblioteca que contiene una clase que me da acceso a la base de
datos. En esta clase tengo métodos que me dejan ejecutar instrucciones tipo
Insert, Delete, etc. (vamos, las ExecuteNonQuery del objeto command),
métodos para obtener un escalar, etc.
Si, por ejemplo, quiero obtener un DataReader con ciertos datos, solo
tengo que hacer lo siguiente: SqlDataReader dr > bd.ObtenerDatos(nombreProcedimientoAlmacenado);
3) Tengo otra capa con los objetos de mi negocio (Clientes, facturas,
productos, etc) que es la que realmente se comunica con la capa de acceso a
datos.
4) Finalmente, el interface solo se ocupa de trabajar con objetos de la capa
de negocio. Si, por ejemplo, quiero grabar un cliente, haré algo parecido a
lo siguiente:
miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

¿Considerais que es un modo correcto de afrontar el desarrollo de una
aplicación?
Muchísimas gracias por vuestra opinión.



Hola, yo no diría que está mal, solo que es mucho trabajo...

Voy a dar una explicación muy sencilla de lo que estoy usando. Después
de cuatro años de desarrollos de aplicaciones reales y mucho trabajo.

La base de todo es aplicar herencia de objetos y controles (o
controles compuestos).

Por tanto el sistema está basado en una clase BaseNegocio de la que
heredan todos los objetos de negocio de la aplicación.
También existe otra llamada ColBaseNegocio que es una colección de
objetos BaseNegocio y que es una clase base para todas las colecciones
de objetos de negocio.
Así puedo tener una coleccion ColDetallePedido (que hereda de
ColBaseNegocio) de la clase DetallePedido (ya que hereda de
BaseNegocio).

Para almacenar los datos del registro actual en la clase BaseNegocio
existe un DataRow. Y para leer y recuperar los datos uso el operador
indizador.

private DataRow dr;

public object this[string index]
{
get
{
try
{
return dr[index];
}
catch
{
throw new ArgumentException("No se ha encontrado el campo " + index
+ " en la tabla.");
}
}
set
{
try
{
dr[index] = value;
LeerID();
}
catch
{
throw new ArgumentException("No se ha encontrado el campo " + index
+ " en la tabla.");
}
}
}

Por tanto la traducción de:
miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

sería (aunque ya ni necesito hacerlo así):
miCliente["Dni"] = txtDni.Text;
miCliente["Nombre"] = txtNombre.Text;
miCliente.Grabar();

Primera "pega", que para recuperar un dato, tengo que hacer cast:
txtNumero.Text = (int) miCliente["Numero"]; // y tener cuidado
con DBNull.
txtNombre.Text = miCliente["Nombre"].ToString();

Pero con esto evito hacer los get/set con los 20 campos y además el
this["PuedeSerDeCualquierCosaAunqueNoSeaUnCampo"]

BaseNegocio acaba haciendo un montón de trabajo (mucho foreach para
leer, guardar, crear, eliminar, buscar, permisos de usuario...) que no
hay que programar una y otra vez en las clases "hijas" y para el resto
del "trabajo" existen métodos virtuales que se pueden sobreescribir en
cada clase.

Con ColBaseNegocio pasa lo mismo, se encarga de mantener la lista de
objetos (p.e. ColDetallePedido es coleccion de DetallePedido) y de la
relación con el objeto "padre" (p.e. Pedido que contiene una instancia
de ColDetallePedido que lee/escribe con el Pedido).
(Obviamente existe un mecanismo para poblar una colección de objetos a
partir de un DataTable, y muchas cosas más).

Aparte de esto, para la interacción con el usuario, existen controles
de usuario que se encargan de leer y escribir datos en las clases de
negocio antes de ser guardadas, o sea controles que heredan o son
compuestos de; TextBox, ComboBox, CheckBox, HyperLink, Button,
LinkButton, DataGrid, DataList, UserControl...

No digo que sea perfecto, ni que no me haya causado problemas. Pero
estoy contento ya que en cada nuevo proyecto, solo tengo que
preocuparme de lo realmente importante de la aplicación, o sea, de
todo menos la "fontanería", jeje.
Por otro lado también es una gozada encontrar un error y saber que
solo tengo que arreglarlo en la clase o el control base para que no se
vuelva a producir en cualquier otra parte de la aplicación.

Saludos,

Paco Ferre
Respuesta Responder a este mensaje
#20 Alberto
31/01/2007 - 19:56 | Informe spam
Yo tengo un concepto parecido de mi modo de hacer las cosas. Entre
aplicación y aplicación mantengo controles de usuario y la capa de acceso a
datos.

"Paco Ferre" escribió en el mensaje
news:
On 30 ene, 21:08, "alberto" wrote:
Menuda pregunta, no??

Os quiero contar brevemente cómo planteo el desarrollo de los proyectos
sencillos:

1) Trabajo con SQL Server y todas las instrucciones sql las almaceno como
procedimientos almacenados.
2) Tengo una biblioteca que contiene una clase que me da acceso a la base
de
datos. En esta clase tengo métodos que me dejan ejecutar instrucciones
tipo
Insert, Delete, etc. (vamos, las ExecuteNonQuery del objeto command),
métodos para obtener un escalar, etc.
Si, por ejemplo, quiero obtener un DataReader con ciertos datos, solo
tengo que hacer lo siguiente: SqlDataReader dr > bd.ObtenerDatos(nombreProcedimientoAlmacenado);
3) Tengo otra capa con los objetos de mi negocio (Clientes, facturas,
productos, etc) que es la que realmente se comunica con la capa de acceso
a
datos.
4) Finalmente, el interface solo se ocupa de trabajar con objetos de la
capa
de negocio. Si, por ejemplo, quiero grabar un cliente, haré algo parecido
a
lo siguiente:
miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

¿Considerais que es un modo correcto de afrontar el desarrollo de una
aplicación?
Muchísimas gracias por vuestra opinión.



Hola, yo no diría que está mal, solo que es mucho trabajo...

Voy a dar una explicación muy sencilla de lo que estoy usando. Después
de cuatro años de desarrollos de aplicaciones reales y mucho trabajo.

La base de todo es aplicar herencia de objetos y controles (o
controles compuestos).

Por tanto el sistema está basado en una clase BaseNegocio de la que
heredan todos los objetos de negocio de la aplicación.
También existe otra llamada ColBaseNegocio que es una colección de
objetos BaseNegocio y que es una clase base para todas las colecciones
de objetos de negocio.
Así puedo tener una coleccion ColDetallePedido (que hereda de
ColBaseNegocio) de la clase DetallePedido (ya que hereda de
BaseNegocio).

Para almacenar los datos del registro actual en la clase BaseNegocio
existe un DataRow. Y para leer y recuperar los datos uso el operador
indizador.

private DataRow dr;

public object this[string index]
{
get
{
try
{
return dr[index];
}
catch
{
throw new ArgumentException("No se ha encontrado el campo " + index
+ " en la tabla.");
}
}
set
{
try
{
dr[index] = value;
LeerID();
}
catch
{
throw new ArgumentException("No se ha encontrado el campo " + index
+ " en la tabla.");
}
}
}

Por tanto la traducción de:
miCliente.Dni = txtDni.Text;
miCliente.Nombre = txtNombre.Text;
miCliente.Grabar();

sería (aunque ya ni necesito hacerlo así):
miCliente["Dni"] = txtDni.Text;
miCliente["Nombre"] = txtNombre.Text;
miCliente.Grabar();

Primera "pega", que para recuperar un dato, tengo que hacer cast:
txtNumero.Text = (int) miCliente["Numero"]; // y tener cuidado
con DBNull.
txtNombre.Text = miCliente["Nombre"].ToString();

Pero con esto evito hacer los get/set con los 20 campos y además el
this["PuedeSerDeCualquierCosaAunqueNoSeaUnCampo"]

BaseNegocio acaba haciendo un montón de trabajo (mucho foreach para
leer, guardar, crear, eliminar, buscar, permisos de usuario...) que no
hay que programar una y otra vez en las clases "hijas" y para el resto
del "trabajo" existen métodos virtuales que se pueden sobreescribir en
cada clase.

Con ColBaseNegocio pasa lo mismo, se encarga de mantener la lista de
objetos (p.e. ColDetallePedido es coleccion de DetallePedido) y de la
relación con el objeto "padre" (p.e. Pedido que contiene una instancia
de ColDetallePedido que lee/escribe con el Pedido).
(Obviamente existe un mecanismo para poblar una colección de objetos a
partir de un DataTable, y muchas cosas más).

Aparte de esto, para la interacción con el usuario, existen controles
de usuario que se encargan de leer y escribir datos en las clases de
negocio antes de ser guardadas, o sea controles que heredan o son
compuestos de; TextBox, ComboBox, CheckBox, HyperLink, Button,
LinkButton, DataGrid, DataList, UserControl...

No digo que sea perfecto, ni que no me haya causado problemas. Pero
estoy contento ya que en cada nuevo proyecto, solo tengo que
preocuparme de lo realmente importante de la aplicación, o sea, de
todo menos la "fontanería", jeje.
Por otro lado también es una gozada encontrar un error y saber que
solo tengo que arreglarlo en la clase o el control base para que no se
vuelva a producir en cualquier otra parte de la aplicación.

Saludos,

Paco Ferre
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida