Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 28-07-2008
Kenobi Kenobi is offline
Miembro
 
Registrado: mar 2007
Posts: 191
Poder: 18
Kenobi Va por buen camino
Programacion orientada a Objetos...duda total....

La verdad entiendo por encima esto de la POO pero de alli a saber implementarla nada que ver ... es por eso que me permito colocarles aca unos procedimientos y funciones sencillos (de esos que uno usa) para ver si alguno de ustedes propone la trasformacion de estos a el paradigma de POO y asi ver de forma practica la trasformacion de un codigo a otro y entender cual es el beneficio de una forma de programar frente a la otra(tradicional, procedimental etc)

OJo las rutinas son muy sencillas...esa es la idea para que se entienda facil...


Código Delphi [-]
procedure TForm2.Modificar(Id: string);
begin
   if Buscar  then
   Begin
   Tabla.edit;
     TablaCampo1.value:=Valor1;
     TablaCampo2.value:=Valor2;
     TablaCampo3.value:=Valor3;
     // ......
     // .....
     // ...

     Tabla.post;
   End
   else MiMensaje('No encontrado');

end;

Function TForm2.Buscar(Id: string):Boolean;
begin
   if Tabla.locate('Id',Id,[]) then result:=True
                                else result:=False;

end;

procedure TForm2.MiMensaje(Texto: string);
begin
   application.MessageBox(Texto,'Aviso del Sistema',MB_OK);

end;

Espero que alguien se tome la molestia asi aprendo de una vez por todas porque con los libros la información queda algo esoterica.....

Gracias .....
P.D: si pueden explicar lo que hicieron pasito a pasito para nosotros los bruticos ....y hacer algo asi como una justificacion de lo que proponen (se que es mucho pedir pero que le vamos a hacer hoy llegue mendigo y sinverguenza)...
Responder Con Cita
  #2  
Antiguo 29-07-2008
Kenobi Kenobi is offline
Miembro
 
Registrado: mar 2007
Posts: 191
Poder: 18
Kenobi Va por buen camino
....?

....?
....?
....?
Responder Con Cita
  #3  
Antiguo 29-07-2008
Avatar de felipe88
[felipe88] felipe88 is offline
Miembro Premium
 
Registrado: may 2007
Ubicación: Mi Valle del Cauca... Colombia!!!
Posts: 1.120
Poder: 18
felipe88 Va por buen camino
Pues amigo kenobi quedo igual ???

No se a que viene el "Paradigma de la POO" con el codigo que nos muestras... representarlo como?... conceptos de Clases, Herencia, Polimorfismo... etc. ??

Si quieres algo que te ponga a prueba en estos conceptos, te recomiendo Java
__________________
Web
Responder Con Cita
  #4  
Antiguo 29-07-2008
Avatar de RolphyReyes
RolphyReyes RolphyReyes is offline
Miembro
 
Registrado: ago 2004
Ubicación: Santo Domingo
Posts: 285
Poder: 20
RolphyReyes Va por buen camino
Smile

Saludos.

Pues te puedo recomendar que leas el libro de Ian Marteens, La Cara Oculta de Delphi 4. Si mal no recuerdo creo que esta en el wiki del club y de paso aprovecha unos ejemplos que tienen en el mismo.
__________________
Gracias,
Rolphy Reyes
Responder Con Cita
  #5  
Antiguo 29-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola Kenobi,

Disculpame si me excedo o me extiendo demasiado al tratar de explicar el asunto.

El tema es que es un tanto complicado entenderlo con los forms. Crease o no, lo que tiene ese código es POO. El tema está en que no es tan fácil verlo.

Analicemos parte por parte para ver si se logra entenderlo ¿OK?

1. Primera cuestión: Cuando uno añade un nuevo form (File -> New -> Form), está definiendo una clase, que desciende por lo general de la clase TForm. Es por ello que en la unit aparece algo como esto:

Código Delphi [-]
type
  TForm1 = class(TForm);
  ...

En este caso definimos una clase llamada TForm1. Que inicialmente aparece vacía.

2. Al ser una declaración, más no un objeto, necesitamos una variable de dicho tipo (Form1) para trabajar con la clase. Esto no los hace Delphi solito, y puede verse más abajo:
Código Delphi [-]
var
  Form1: TForm1;

Entonces, ya tenemos nuestra clase y una variable para trabajar con ella.

3. ¿Cómo y cuando se crea? Por regla general Delphi cuando uno añade una Form (no quiero usar el término crear puesto que se contradice con el verdadero significado en POO) se encarga de ello. Ve a la unidad dpr. Uno observa esto:

Código Delphi [-]
program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Si observas, en uses tenemos declarada el nombre de la unidad correspondiente al form. Y más abajo, una vez que se inicia la aplicación, se invoca al método CreateForm con los parámetros TForm1 y Form1. Si recuerdas, Form1 es la variable definida en la Unit1.

He dicho antes "Por regla general", y esto es así debido a que no necesariamente todas las forms van a crearse automáticamente al iniciarse la aplicación. En ocasiones necesitaremos dar nosotros el control de cuando y donde crearse, por tanto necesitamos eliminar del dpr dicha declaración y dar la orden explicitamente de cuando crear una form. Para ello hay dos opciones:
1. Nos vamos a Proyect -> Options -> Forms y trasladamos los Form1 necesarios a la parte Available Forms.
2. O bien, simplemente borramos en el dpr los CreateForm que sean necesarios.

Una cuestión interesante a tratar es el manejo de forms en forma modal, y si es un entorno MDI o MSI. Cuando uno crea una instancia de un Form debe tener presente si ciclo de vida. Estas son cuestiones que escapan un poco al tema, hay hilos que debaten estas cuestiones técnicas (un tema que en ocasiones se deja de lado).

Por mi parte voy a seguir el tema más cerca de POO.

Bueno tenemos un clase vacia, una variable, y en caso más simple... dejamos a Application que se encargue de crear y liberar los forms. Necesitamos ahora darle vida a esta clase. Vamos al punto 4.

4. Dandole vida a nuestra clase.
Cuando uno añade controles a la clase, le está definiendo campos. Por defecto Delphi asume la visibilidad publica. Por tanto cuando veas esto:

Código Delphi [-]
type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
 ....

Quiere decir que Button1, Edit1 y Memo1 son campos públicos. Cada campo es de un tipo. Button1 es de tipo TButton, y asi sucesivamente.

Como tipos, son definiciones de más clases. Por tanto, cuando uno añade un control está colocando un "objeto" y le está indicando que su dueño es el form al que fue añadido.

Dije "objeto". Pero en realidad no lo es... ¿marea un poquito no es cierto? Veamos.... Si Form1 es una variable, Button1 también lo es. De hecho, un campo es una variable.
El problema es que Delphi lo hace tan automático, y tan fácil la vida que nos hace creer que tenemos objetos. La realidad es que cuando se cree el Form, recién tendremos los objetos Button1, Edit1, Memo1.

¿Recuerdas que antes dije que el Form es el dueño? Este es el comportamiento por defecto que asume el compilador. Como dueño, Form1 tiene la responsabilidad de crear y liberar o destruir (son cosas un tanto diferentes, por ahora podemos asumirlas como sinónimos) los controles hijos que posee.

Aun no tenemos definido el comportamiento. Tenemos controles declarados. Veamos que hace cada uno.

Como controles, cada uno cumple su función o rol. Un Button1 cumplirá los propósitos de un botón, un Edit1 el de un cuadro de texto, etc. En el inspector de objetos, cuando seleccionamos algún componente, aparece una lista de propiedades y eventos.

La regla general dice: las propiedades nos permiten tener acceso (de lectura y/o escritura) a los campos privados de dicho objeto. Dependiendo del valor de dichas propiedades el control se mostrará (y actuará) de una u otra forma.
Los eventos son una serie de mensajes programables que se envían y reciben al SO. Acabo de decir una verdad a medias.

Pongamos un ejemplo. Cuando uno hace clic en un botón, el form recibe dicho mensaje y se lo envia a un objeto intermediario entre él y el SO. ¿Recuerdas aquel Application? Es este desconocido quien actua de intermediario.

Entonces: pulsamos en el botón, este envia el mensaje al form, el form a Application y Application al SO. Luego el SO responde, se lo hace saber a Application, éste al Form y luego al botón.

En realidad un evento es un puntero a un método. Asusta un poco esa palabra. Los eventos son acciones que se van a hacer cuando sucedan dichos mensajes que se envian. No estás obligado a usarlos. Simplemente el compilador interpreta que si no se asignó algo al evento, lo ignore y siga su paso.

Cuando algo en control (mejor dicho objeto) cambia, este envia mensajes... cuando se detecta el mensaje se pregunta si hay algún interesado en hacer algo. Veamos un caso práctico: Pulsa doble click en el Edit1.

Vemos en la unit esto:
Código Delphi [-]
type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Edit1Change(Sender: TObject);
...

procedure TForm1.Edit1Change(Sender: TObject);
begin

end;
...

¿Que sucedió? Simplemente se ha añadido un método al form. En este caso, se llama Edit1Change. Y en la sección implementation vemos que se ha dado la estructura básica al método. Es allí donde definiremos que y como interpretar un mensaje. Le estamos dando una respuesta.

Constantemente los controles dan y reciben mensajes. Si estamos interesados en interceptar alguno, simplemente tenemos que declarar una respuesta: un método. Internamente, un puntero apuntará al método que hemos declarado y ejecutará dichas rutinas.

Si te fijas, en la implementación de este método se ve un TForm1.EditChange. Esto quiere decir que en este caso, quien dispará el método es TForm1. Se lo denomina Emisor. A continuación aparece Edit1Change. Esto quiere decir que el receptor del evento onChange es Edit1.

En un evento tiene lugar el emisor y el receptor. No necesariamente deben ser objetos distintos. Por ejemplo, al declarar un método al evento OnClose del Form se ve claramente que el emisor y el receptor son Form1.

Delphi nos hace la tarea más fácil al ocultarnos los mensajes (algo un tanto más complejo. No estoy demasiado puesto en el tema, y no viene mucho al caso)... simplemente nos limitamos a dar respuesta. Los controles que añadimos a un Form son intermediarios, y dan más funcionalidad al objeto TForm1.

Bueno sigamos.... estuve hablando de eventos y métodos. Los métodos no necesariamente son para dar respuesta a los mensajes que se envian y reciben desde el SO. Pueden ser simples procedimientos y funciones que se le declaran al emisor para cumplir con los propósitos para los cuales a sido definido.

Por ejemplo, si nuestro TForm1 está pensado para hacer operaciones de búsqueda tal vez nos interese tener un método Buscar, un método BuscarSiguiente, etc.

Si esos métodos son procedimientos o funciones, eso es ya a gusto y necesidades de implementación. Lo importante es definir la visibilidad y alcance de dichos métodos. Un ejemplo:

Código Delphi [-]
type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Edit1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FTexto: string;
    function SoloTexto: boolean;
  public
    { Public declarations }
    procedure Buscar(Texto: string);
    function BuscarSiguiente: boolean;
  end;

He declarado un campo FTexto y un método SoloTexto con visibilidad privada. Hay dos métodos públicos: Buscar y BuscarSiguiente.

El propósito es ocultar guardar en FTexto el texto a buscar, SoloTexto se encargará de determinar que el contenido a buscar sea exclusivamente texto y no se permitan numeros y caracteres extraños. SoloTexto será invocado internamente por Buscar (no es necesario, al menos según este análisis, que SoloTexto sea declarado público).

En tu caso definiste los métodos Buscar, MiMensaje y Modificar.

El objetivo de los métodos es para disparar nuevos métodos o enviar mensajes hacia otros objetos a que hagan algo (estos mensajes son diferentes a los que se envian al SO, no confundirlos).

Por ejemplo, cuando uno tiene algo como esto:

Código Delphi [-]
procedure TMiObjeto.HacerAlgo(Valor: integer);
begin
  ObjetoEsclavo.HacerEsto(Valor);
end;

Le está dando el mensaje de HacerEsto a ObjetoEsclavo. Luego, ObjetoEsclavo realizará dicho método.

Espero que se vaya entendiendo el asunto.

Un objeto puede tener propiedades, campos, métodos, eventos. Como y que hacer... eso es ya cuestiones de implementación.

TForm1, como una declaración de una clase, puede tener nuevos métodos, propiedades, campos, y eventos. Es más hasta se le puede aplicar herencia. Tranquilamente podemos tener esto:

Código Delphi [-]
TFormHijo = class(TForm1);
...

El tema de la herencia, ya sería un poco más rebuscado y se sale de esta ya extensa explicación (y aún no se si con esto se entiende el tema).

Sugiero que practiques el tema de POO definiendo tus objetos fuera de los forms. Define tus propias clases y practica. Como te han sugerido, lee la cara oculta. Allí está explicado en el capítulo 6 el tema de POO. Creo que con lo dicho por Ian Marteens y esto, y una búsqueda en los foros sobre este tema (en otras ocasiones se lo ha tratado) se puede entender mejor.

Disculpen el rollo que me he mandado.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #6  
Antiguo 29-07-2008
Avatar de felipe88
[felipe88] felipe88 is offline
Miembro Premium
 
Registrado: may 2007
Ubicación: Mi Valle del Cauca... Colombia!!!
Posts: 1.120
Poder: 18
felipe88 Va por buen camino
Amigo Delphius, te sobraste con esa respuesta ... quien lo habria pensado y explicado mejor.
__________________
Web
Responder Con Cita
  #7  
Antiguo 29-07-2008
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Hola Delphius,

No entiendo esto del emisor y receptor. ¿Que el emisor (sender) en TForm1.EditChange no es el mismo Edit?

Yo tenía la idea de que si un objeto A llama al método M de un objeto B:

Código Delphi [-]
// desde algún método de A

B.M;

entonces A manda el mensaje M a B, siendo A el emisor y B el receptor.

¿Cómo es en este caso?

// Saludos
Responder Con Cita
  #8  
Antiguo 29-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Hola roman,
Tienes razón, metí mal la pata

El emisor es quien envía la orden, el emisor quien recibe.

Lo que debería haber dicho en ese caso, es que en cuestiones de eventos el emisor es quien da la orden, y el receptor es el método que implementamos para dar respuesta a la orden.

Por ejemplo, cuando se ejecuta el evento OnChange en el Edit, el emisor (Sender) es TEdit, y el receptor es el método implementado en el Form; Edit1Change en este caso.

Se me han liado los cables en la cabeza, disculpen.

Muchas gracias por la observación amigo roman

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #9  
Antiguo 29-07-2008
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Delphius,

De todas formas no puedo menos que estar de acuerdo con Felipe, y aunque comentas que ya sería más rebuscado, yo apreciaría mucho que en un momento de inspiración te aventaras con una breve introducción a OOP, puesto que pienso que entender conceptos como herencia, encapsulamiento y polimorfismo, antes aún que los formularios, es algo que (nos) vendría bien a muchos. Ni qué decir que sería estupendo si incluyes conceptos como composición, asociación, etc., que pocos libros para novatos tratan.

Cuando programamos con Delphi, usamos OOP implícitamente, tal como lo has hecho ver, pero en realidad muchos ignoramos lo que es realmente estructurar una aplicación usando OOP, y una explicación de estas que acostumbras, sería muy ilustrativa para muchos.

Desde luego, no corre prisa

// Saludos
Responder Con Cita
  #10  
Antiguo 29-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
Delphius,

De todas formas no puedo menos que estar de acuerdo con Felipe, y aunque comentas que ya sería más rebuscado, yo apreciaría mucho que en un momento de inspiración te aventaras con una breve introducción a OOP, puesto que pienso que entender conceptos como herencia, encapsulamiento y polimorfismo, antes aún que los formularios, es algo que (nos) vendría bien a muchos. Ni qué decir que sería estupendo si incluyes conceptos como composición, asociación, etc., que pocos libros para novatos tratan.

Cuando programamos con Delphi, usamos OOP implícitamente, tal como lo has hecho ver, pero en realidad muchos ignoramos lo que es realmente estructurar una aplicación usando OOP, y una explicación de estas que acostumbras, sería muy ilustrativa para muchos.

Desde luego, no corre prisa

// Saludos
Muchas gracias Roman y felipe por sus palabras.

No soy un experto en POO con Delphi, pero hago lo que puedo.
Estoy elaborando algunos borradores sobre el uso de patrones. En la medida en que los voy poniendo en práctica (y me siento seguro de que lo diga sea correcto) y puedo sacar tiempo para sentarme tranquilo y ordenar las ideas.

Elaborar un "documento" como el que mencionas sirve a muchos. Puede que mi abstracta mente pueda servir de ayuda, más tendría que tener cuidado de no ser demasiado abstracto y tener algunos pies en la tierra (cosa que no me es fácil) porque puede hacer más difícil explicarlo.

Puede que la unión de esos documentos y ejemplos que estoy preparando sirvan para ir tratando la POO en su conjunto. Pero no estaría nada mal tener uno exclusivamente para tratar los conceptos más básicos de POO, ya que el uso de los patrones implica que se da por hecho los conceptos básicos.

Déjame ver que sale de esto. Si alguien más se anima, pues no tiene que pedirme permiso, puede comenzar sin mi.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #11  
Antiguo 29-07-2008
esocrates esocrates is offline
Miembro
 
Registrado: may 2003
Ubicación: Argentina
Posts: 210
Poder: 21
esocrates Va por buen camino
Me sumo al agradecimiento a Delphius por esta estupenda lección.
Un saludo a todos
Responder Con Cita
  #12  
Antiguo 29-07-2008
Kenobi Kenobi is offline
Miembro
 
Registrado: mar 2007
Posts: 191
Poder: 18
Kenobi Va por buen camino
Gracias.....

Que mas puedo decir Gracias....

Ahora bien delphi aplica la POO directo en su funcionamiento, la pregunta que me falta responder es ....tiene algun sentido crear algo asi como clases para implementar labores regulares tales como abrir,cerrar,buscar,modificar

o sea no se si soy claro pero vale la pena enrollarse con esto y cual es el beneficio añadido a hacer lo que procedimentalmente se acostumbra . que es

en mi caso ...

creo varios procedures y funciones con parametros (algunos de tipo objeto)
los cuales llamo desde los eventos de los controles ....

aun asi Gracias .....
Responder Con Cita
  #13  
Antiguo 30-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por Kenobi Ver Mensaje
Que mas puedo decir Gracias....

Ahora bien delphi aplica la POO directo en su funcionamiento, la pregunta que me falta responder es ....tiene algun sentido crear algo asi como clases para implementar labores regulares tales como abrir,cerrar,buscar,modificar

o sea no se si soy claro pero vale la pena enrollarse con esto y cual es el beneficio añadido a hacer lo que procedimentalmente se acostumbra . que es

en mi caso ...

creo varios procedures y funciones con parametros (algunos de tipo objeto)
los cuales llamo desde los eventos de los controles ....

aun asi Gracias .....
Hola Kenobi, es bueno que te hayas preguntado eso. Y la respuesta más certera... es un depende.

Cuando uno se mete en la POO empieza a preguntarse sobre si la relación Costo/Beneficio , Esfuerzo/Tiempo es viable.

Primeramente deberías preguntarte, en que medida, los métodos abrir, cerrar, buscar, modificar, que mencionas te permiten reutilizar y minimizar código y acelerar tu trabajo.

En ocasiones un enfoque estrictamente purista es más costoso para proyectos chicos, y que poseen poco mantenimiento. Pero para un proyecto enforme o relativamente grande, un enfoque más centrado hacia la POO es más útil.

Yo, a grandes rasgos distingo dos tipos de clases:
Clases de propósito general
Clases del dominio

Las primeras son aquellas clases que implementan métodos que pueden servir de propósito general a cualquier aplicativo. el framework que posee Delphi, su VCL es un buen ejemplo. Pero no termina en la VCL, uno puede definirse sus propias clases para estos propósitos. Un framework de persistencia es otro ejemplo.

Y las segundas son las clases diseñadas para dar respuesta al dominio o ambiente. En pocas para representar la solución del problema. Por ejemplo, un diseño estructurado en POO para dar respuestas a un sistema de control de tráfico aereo (si... un ejemplo grande) o el diseño de un control de inventario.

Ahora bien, existe un "peligro" de que clases del dominio se conviertan en clases de propósito general. Dije "peligro" porque no necesariamente es un problema. El problema se presenta cuando uno se prepara para el cambio.

Por poner un ejemplo. Digamos que tengo en mis manos un pequeño "framework" que permite trabajar y aplicar conceptos sobre técnicas de simulación. Este framework tiene el potencial de ser parte de un sistema único como puede ser aplicable a muchos enfoques.

¿De de que se trata? ¿De algo de propósito general? ¿O algo exclusivamente para un modelo en específico?

Lo hago más simple... una clase TCliente ¿Es una clase que sirve como propósito general?¿O por el contrario, está concebida para ser usada en un sistema de Gestión?

Un diseño estructurado en una jerarquia amplia y sólida tiene una misma ventaja y desventaja.
Al ser un diseño rígido nos trae la ventaja de que se posee clases estables. Pero además, puede llegar a limitarnos y cabe la posibilidad de dificultar ampliar la jerarquia o aplicar ciertos cambios.

A su vez, un diseño blando tiene la dificultad de sus clases están debilemente diseñadas y no son muy estables, tendiendo a "explotar" cuando cambiamos algo en otro lado. Pero a su vez, puede que nos haga más fácil nuevas adaptacaciones.

El punto es que no hay un diseño único que nos garantice que todo va a funcionar. La experiencia que adquiere uno con el tiempo nos lleva a buscar un equilibrio entre lo rígido y lo flexible.

Como lo dice la frase de Tao, señalada a el libro UML y Patrones:
Cita:
Empezado por Tao Te Ching
Lo duro y rígide se rompe. Lo flexible prevalece
Esto no quiere decir que debas optar por un diseño débil entre las clases. Sino que representa la idea de buscar ese equilibrio.

No puedo decirte si tiene sentido hacer lo que haces, tendría que verlo, y aun asi... no me atrevería a juzgarlo demasiado. Puesto que una buena dosis de realidad que me ha demostrado en este tiempo que llevo aprendiendo sobre POO que no existe un diseño bueno o malo.

¡Bienvenido a la subjetividad!

Si tus clases te permiten armonizar cómodamente a ti el trabajo, ese diseño para ti es bueno. Puede que a mi, tu diseño me indique otra cosa.
Si tu tienes 20 clases y te funciona, perfecto. Si yo tengo 30 y me funciona también... perfecto.

¿Es mi diseño más complejo que el tuyo? Es posible, o guarda... puede que el mio en realidad sea más simple. Todo dependerá de como estén trabajando tus clases.
No es lo mismo 20 clases trabajando para dar respuesta un problema que 30.

¿Se entiende a lo que quiero llegar?
Tus 20 clases es posible que estén mucho mas acopladas que mis 30. Por otro lado yo corro el riesgo de tener clases inútiles que poco aportan al dominio, y todo por conseguir un bajo acoplamiento.

Ahora, ¿es lo mismo que yo 15 y tu 20?
Otra vez hay que analizar. Quien sabe... es posible que algunas clases que tu definiste es mejor generalizarlas en una o dos. Y esto puede también afectar tanto al acoplamiento como la cohesión.

No se puede separar el acoplamiento de la cohesión. Si bien no son dos caras de la misma moneda, uno afecto a otro.

Si fuedes generalizar o factorizar clases, hazlo.

Recomiendo que le des una leída al libro UML y Patrones. Una Introducción al Análisis y Diseño Orientado a Objetos y al Proceso Unificado. Su autor es Craig Larman. En cualquier librería o biblioteca dedicada a informática lo puedes encontrar. En un libro de cabecera muy solicitado.

Este libro puede ayudarte a ver la POO desde otra perspectiva.

No quiero despedirme de este post sin antes preguntarte algunas cosas, puesto que me invade la duda... ¿hace cuanto estás metiendote en este de POO? ¿Tienes toda tu lógica de negocio o dominio implementada en los forms y/o datamodules?

Estas preguntas te las digo para saber que tanto estás asimilando de estos conceptos. No todos es formas y controles. Por ello sugiero practicar el diseño de objetos fuera de lo que es la VCL, definiendo tus propias clases. Me parece que esa es una buena de analizar si uno está entiendo bien las cosas.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #14  
Antiguo 30-07-2008
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Otra cosa:

La POO cuando es algo que debe venir de forma natural. Siempre me ha parecido que es un atentado a la educacion cuando a la gente en su curso introductorio le dan el tema del polimorfismo o de patrones y todo eso. Es como uno estar en un curso de cocina y que empiezen por explicarle las diversas famialias de frutas, verduras, carnes, condimentos y todo eso.

Lo unico que hay que saber para ser un "duro" con la programacion es esto:

* Los sustantivos son los nombres de las clases (ej: Ventana, Cliente)
* Los adjetivos, sus propiedades (Alto, Ancho)
* Los verbos son las acciones que:
- Si son verbos directos, metodos (Close)
- Sin son verbos preguntones, funciones (CanClose())
- Sin son verbos de "momentos" son eventos (WhenClose())

Usar nombres claros y directos. Si pones:

Cita:
EsActivo
y lo documentarias como:

Cita:
Funcion que determina si el cliente es valido
entonces dejate de bobadas y cambialo por

Cita:
EsValido
y te ahorraste la documentacion

- Haz pedazos de codigo que sean concisos y se dedican a una sola cosa.

- Haz clases que se encargen de mover las acciones de un lado a otro. Clases de control (ej: Para mover un inventario). No mezcles clases que controlan con clases que informan o que definen una entidad simple a menos que haya muy poco que controlar.

- Haz codigo testeable. Metete en el asunto de TTD (Test Driven Desing). El resultado de un codigo testeable es casi sin equivocacion una excelente POO.

- Cuando creas que algo esta mal hecho, esta mal hecho.

- No uses ejemplos de Java o C* para aprender OO. Por regla general son muy complicados. Lee pascal, o python. Son los lenguajes que por regla general tienen las soluciones mas sencillas posibles

Leete y aprendete el Zen de python, y aplicalo en Delphi:
Cita:
* Bello es mejor que feo.
* Explícito es mejor que implícito.
* Simple es mejor que complejo.
* Complejo es mejor que complicado.
* Plano es mejor que anidado.
* Disperso es mejor que denso.
* La legibilidad cuenta.
* Los casos especiales no son tan especiales como para quebrar las reglas.
* Aunque la practicidad le gana a la pureza.
* Los errores nunca deberían dejarse pasar silenciosamente.
* A menos que hayan sido silenciados explícitamente.
* Frente a la ambigüedad, rechazar la tentación de adivinar.
* Debería haber una -y preferiblemente sólo una- manera obvia de hacerlo.
* Aunque esa manera puede no ser obvia al principio a menos que usted sea Holandés.
* Ahora es mejor que nunca.
* Aunque nunca es a menudo mejor que ya.
* Si la implementación es dificil de explicar, es una mala idea.
* Si la implementacion es fácil de explicar, puede que sea una buena idea.
__________________
El malabarista.
Responder Con Cita
  #15  
Antiguo 30-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Mario, ¡excelente resumen!
¡Bellísimamente simple! Más directo y preciso de decir, no hay!

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #16  
Antiguo 30-07-2008
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
A ver, un ejemplo-pregunta, porque así como lo dice Mario suena muy fácil, pero..

Tengo un sistema que gestiona las inscripciones de alumnos a distintos cursos. Una inscripción no puede hacerse así como así, debe cumplir ciertas reglas. Puedo tener mis clases Alumno y Curso (mis sustantivos).

¿Dónde hago la inscripción?

Código Delphi [-]
Alumno.Inscribir(Grupo);

o

Código Delphi [-]
Grupo.Inscribir(Alumno);

o bien una clase aparte:

Código Delphi [-]
Reglamento.Inscribir(Alumno, Grupo);

// Saludos
Responder Con Cita
  #17  
Antiguo 30-07-2008
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Donde parezca mejor.

Cuando se trata de modelar un proceso de negocio, probablemente el mismo proceso dice como se hace.

Quien hace la inscripcion? El alumno? El profesor?. (Ok, no es pa' poner una clase llamada TJulianitaLaSecre!). En tal caso seguramente hay un proceso de inscripcion.

Pero si lo UNICO que hace ese proceso es inscribir, pues que bobada hacer otra clase. En tal caso, si no hay un workflow lo mas simple es entender que la inscripcion de un alumno es una forma glorificada de decir: Alumno.... Nuevo.
-------
Yo tambien hice un software para escuelas, que a la fecha ha sido el de mas uso (que yo sepa mas de 3000 escuelas!). Ahora, en esa epoca era mas bien novato, pero en fin....
__________________
El malabarista.
Responder Con Cita
  #18  
Antiguo 30-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
A ver, un ejemplo-pregunta, porque así como lo dice Mario suena muy fácil, pero..

Tengo un sistema que gestiona las inscripciones de alumnos a distintos cursos. Una inscripción no puede hacerse así como así, debe cumplir ciertas reglas. Puedo tener mis clases Alumno y Curso (mis sustantivos).

¿Dónde hago la inscripción?

Código Delphi [-]Alumno.Inscribir(Grupo);


o

Código Delphi [-]Grupo.Inscribir(Alumno);


o bien una clase aparte:

Código Delphi [-]Reglamento.Inscribir(Alumno, Grupo);


// Saludos
Cita:
Empezado por mamcx Ver Mensaje
Donde parezca mejor.

Cuando se trata de modelar un proceso de negocio, probablemente el mismo proceso dice como se hace.

Quien hace la inscripcion? El alumno? El profesor?. (Ok, no es pa' poner una clase llamada TJulianitaLaSecre!). En tal caso seguramente hay un proceso de inscripcion.

Pero si lo UNICO que hace ese proceso es inscribir, pues que bobada hacer otra clase. En tal caso, si no hay un workflow lo mas simple es entender que la inscripcion de un alumno es una forma glorificada de decir: Alumno.... Nuevo.
-------
Yo tambien hice un software para escuelas, que a la fecha ha sido el de mas uso (que yo sepa mas de 3000 escuelas!). Ahora, en esa epoca era mas bien novato, pero en fin....
Hola,
Pues no se si lo interpreto adecuadamente... pero por lo que entiendo... si no existe o no se tiene conocimiento de que exista un motivo en particular para decir que el proceso de incripción aporta valor al negocio, entonces tener esa tercera clase no aporta nada. No tiene sentido.
Ahora con respecto a cual de las otras dos opciones es válida, yo deduzco ,por la breve descripción de roman, que es preferible la primera opción que a la segunda.
Me parece más apropiado semanticamente hablando decir:

Código Delphi [-]
Alumno.Inscribir(Grupo);

que decir

Código Delphi [-]
Grupo.Inscribir(Alumno);

Ahora bien, si existe una buena razón para justificar que la presencia de este proceso tiene cierto valor de negocio, y si obedece a ciertas reglas, entonces a mi modo de ver es preferible tener una clase TReglaIncripcion.
Y el modo que emplearía para saber si se cumple dicha regla sería algo asi:

Código Delphi [-]
procedure TAlumno.Inscribir(Grupo: TGrupo);
begin
...
if ReglaInscripcion.IncripcionValida(Self, Grupo)
  then Inscribir(Grupo)
  else ....
...
end;

Es decir, dejo a la clase TReglaInscripcion que determine si es válido el proceso. Ya como está implementada esta clase no viene al caso. Tal vez, tenga clases TReglasNegocio, TReglasNegocioIncripcion, etc... que le asisten en el proceso. No está todo dicho.

En fin creo que se entiende la idea. Yo tendría que saber un poco mejor del dominio para opinar.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #19  
Antiguo 30-07-2008
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Más que nada era un ejemplo pues a mi al menos. me parece justamente que no siempre queda claro qué camino tomar.

En este ejemplo, desde luego hay reglas que seguir, por eso dije que no se hace así como así; no todos los alumnos se pueden inscribir a cualquier curso, se debe tener en cuenta qué tipo de alumno es, cuál es su historia académica, cuántos cursos más lleva, etc.

Ahora, en algunos casos el alumno puede inscribirse él mismo, pero en otros es un personal calificado quien debe hacerlo y en otros más es un proceso automático (algunas reinscripciones), pero en todas las modalidades se deben cumplir una serie de reglas.

No sé qué se entendería porque el proceso en sí tenga un valor de negocio, en mi ingenuidad considero que lo tiene en tanto que existe. Una inscripción es un ente en sí mismo con determinados atributos como la calificación, la fecha en que se realiza, la fecha en que se paga, etc.

Luego entonces ¿sería descabellado poner:

Código Delphi [-]
Inscripcion := TInscripcion.Create;

Inscripcion.Alumno:= Alumno;
Inscripción.Curso := Curso;

if Inscripcion.Validar then
  Inscripcion.Guardar;

de manera que es el mismo objeto Inscripcion el que valida las reglas?

// Saludos
Responder Con Cita
  #20  
Antiguo 30-07-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por roman Ver Mensaje
Más que nada era un ejemplo pues a mi al menos. me parece justamente que no siempre queda claro qué camino tomar.

En este ejemplo, desde luego hay reglas que seguir, por eso dije que no se hace así como así; no todos los alumnos se pueden inscribir a cualquier curso, se debe tener en cuenta qué tipo de alumno es, cuál es su historia académica, cuántos cursos más lleva, etc.

Ahora, en algunos casos el alumno puede inscribirse él mismo, pero en otros es un personal calificado quien debe hacerlo y en otros más es un proceso automático (algunas reinscripciones), pero en todas las modalidades se deben cumplir una serie de reglas.

No sé qué se entendería porque el proceso en sí tenga un valor de negocio, en mi ingenuidad considero que lo tiene en tanto que existe. Una inscripción es un ente en sí mismo con determinados atributos como la calificación, la fecha en que se realiza, la fecha en que se paga, etc.

Luego entonces ¿sería descabellado poner:

Código Delphi [-]Inscripcion := TInscripcion.Create; Inscripcion.Alumno:= Alumno; Inscripción.Curso := Curso; if Inscripcion.Validar then Inscripcion.Guardar;


de manera que es el mismo objeto Inscripcion el que valida las reglas?

// Saludos
Que el proceso tenga valor de negocio significa que para el ambiente o dominio le es útil y representa un elemento más que forma parte de su trabajo, es parte de la organización y/o le da valor agregado.

Una inscripción tiene, al menos yo creo que si, que tiene valor de negocio. Es una actividad central y afecta en otras áreas. Por tanto, es de importancia dos cosas aqui: el proceso y el documento. Es necesario contar con un método que permite dar soporte a esta actividad. Por ejemplo, el nombre InscribirAlumno. Ahora, como valor de negocio, el documento o formulario que se llena es la FichaInscripcion. Puede que realizar una clase que represente a dicho documento les sea de utilidad en un futuro... por ahora no estaría mal añadirla al repertorio.

Entonces, si lo veo asi, yo diría que tenemos las siguientes clases: Alumno, Grupo, FichaInscripcion.

Se estuvo debatiendo la idea de que exista una clase que determine las reglas de inscripción.
Tu enfoque, amigo roman, no es descabellado. Es entendible y si te es una representación viable del dominio, pues sigue.

Si me lo permites, yo lo veo un tanto distinto. Si bien se puede entender que el alumno es el interesado en llevar el método de incribirse (es posiblemente el experto en información), si realmente existe un conjunto de reglas que afectan a esto, yo sugeriría que no posee toda la información necesaria para llevar a cabo dicho propósito. Que sea un experto parcial no es un gran problema, pero a vista de la presencia de la volatilidad de este proceso, es mejor ubicar el grueso del problema de la regla en otro lado.

Es entendible que el interesado sea el alumno, más termina no siendo el quien decide y lleva a cabo el proceso. Puede entenderse, si se le desea verlo (y buscarle una quinta pata al problema), que entre el alumno y el proceso medie algún interesado. Este intermediario muy posiblemente sea el candidato potencial para asumir el proceso estudiado: es el quien tiene más conocimiento e información de como tratar el tema. Ando pensando en un nombre que sea más representativo... si es que en ocasiones es otra persona quien llena la ficha, en otras el estudiante, y en otras una máquina (buscarle la octava)... yo diría que conviene llamarlo ProcesadorInscripcion (ya me diran si el estudio del dominio sugiere otro nombre. Al menos yo lo veo que tantos actores humanos y no humanos hacen uso del ProcesadorInscripcion)

Es este ProcesadorInscripcion quien en definitiva realiza la inscripción. En resumidas cuentas, el algoritmo para mi puede venir así:

Código Delphi [-]
procedure TProcesadorInscripcion.InscribirAlumno(Alumno: TAlumno, Grupo: TGrupo);
var Ficha: TFichaInscripcion;
begin
   if MotorReglaInscripcion.EsValidaInscripcion(Alumno, Grupo)
     then begin
               // Creamos la ficha de inscripción
               Ficha := TFichaInscripcion.Create;
               
               // Llenamos la ficha
               Ficha.Alumno := Alumno;
               Ficha.Grupo := Grupo;
               ...
               Archivar(Ficha);
            end
     else ...
end;

Como puede verse, he añadido una clase MotorReglaInscripcion. Esto está sujeto a debate. Si es posible que las reglas cambien, y que sean un tanto complejas o arbitrarias... me parece adecuado delegar en un motor de reglas que asuma esa responsabilidad y que el Procesador delegue parte del trabajo. Si esta etapa del trabajo (determinar si es válida) no cambia, pues que el método EsValidaInscripcion pertenezca a ProcesadorInscripcion y no exista el motor.

Muy posiblemente ProcesadorInscripcion tenga visibilidad de atributo del motor (si esta motivado su uso). Cabe la posibilidad de que este ProcesadorInscripcion haga poco trabajo, (¿sólo inscribe?) pero al menos deja clara la intención de que nos abstraemos de quien lleva a cabo formalmente la inscripción.

Se ha añadido el objeto FichaInscripcion. Este objeto a mi modo de ver, es quien en realidad termina siendo guardado o archivado (el que mejor convenga), leído y (¿actualizado?). Formalmente decimos que se llena una ficha o acta de inscripción y esto motiva la aparación de esta clase. Y si esta clase representa a dicho documento, es una buena candidata a ser quien termina conservando la información de que el estudiante a sido inscripto.

Puede que mi diseño sea un tanto, liviano... que hay muchas clases que hacen poco. Sólo hemos analizado una pequeña punta de un iceberg.

Podríamos seguir toda la semana con esto... a lo que quiero llegar es a una "simple" pregunta ¿Quién de nosotros tiene razón?

No hay, ni habrá, una única manera de representar un mismo problema. Disculpen nuevamente el rollo.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Programacion Orientada A Objetos sdiaz1983 Varios 8 16-11-2007 02:42:46
Es la Programación Orientada a Arquitectura una evolución de OOP? Roll06lm OOP 4 23-10-2007 00:33:50
programación orientada a aspectos y delphi.. pvizcay Varios 1 08-05-2007 05:06:35
Base Datos orientada objetos TP(DEV) .NET 1 02-03-2007 17:54:20
Programación Orientada a Aspectos marcoszorrilla Debates 17 06-04-2004 23:18:27


La franja horaria es GMT +2. Ahora son las 06:31:56.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi