Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Sugerencias para nombre de método de clase, ¿tú qué nombre le darías? (https://www.clubdelphi.com/foros/showthread.php?t=82424)

Al González 06-03-2013 09:18:22

Sugerencias para nombre de método de clase, ¿tú qué nombre le darías?
 
Ejemplo algo "abstracto":
Código Delphi [-]
  // Esquema normal, usar If:

  If { Cierta verificación de Param } Then
    // Param superó la verificación, creamos la instancia de objeto.
    Obj := TObj.Create (Param)
  Else
    Obj := Nil;  // Param no superó la verificación, asignamos Nil.


  // Esquema alternativo, usar un método de clase:

  { El método de clase "Make" hace la verificación de Param, llamando al
    constructor Create si la supera, o devolviendo Nil si no la supera. }
  Obj := TObj.Make (Param);
En ocasiones la verificación de "Param" es tan intrínseca de la clase (en este caso "TObj"), que pareciera más adecuado (y orientado a objetos) definir en ella un método de clase que haga todo el trabajo: verificar el parámetro y crear el objeto o devolver Nil.

¿Creen que "Make" puede ser un buen nombre estandarizado para ese tipo de métodos?

¿Se les ocurre algún otro que suene más a la tarea realizada? ¿Cuál?

¿Estoy borracho de sueño y debí dormir algunas horas antes de publicar disparates? :confused:

Bueno, saludos y gracias de antemano. Esta mañana, será otro día...

dec 06-03-2013 09:41:54

Hola,

¿MakeOrDie? En todo caso trataría (creo) de dejar claro que trata de crear un objeto, pero, que, es posible que no se termine creando. Así que "MakeOrDie", "MakeIfPossible", "MakeFromParams",... "CreateFromParams"... ¡Lo siento! ¡no soy muy bueno poniendo nombre a nada! :D

Neftali [Germán.Estévez] 06-03-2013 10:32:39

Yo voto por la tercera opción...

No, no la de "MakeFromParams", sino la de que "te vayas a dirmir un rato...." :D:D:D

Si aun sigues con eso cuando te levantes, tal vez un "TryCreate",...

Código Delphi [-]
  Obj := TObj.TryCreate(Param);

dec 06-03-2013 11:29:51

Hola,

+1 al "TryCreate", aunque, todo esto me deja una rara sensación, como que no entiendo muy bien que uno espere "nil" de esta forma... entonces habría de comprobarse después si el objeto ha sido o no creado. Ahora bien, ¿qué tal el uso de excepciones? Se le pasan los parámetros a cierto método, y, este levanta determinada excepción si los parámetros no son válidos y el objeto no puede ser creado. ¿Qué os parece? :)

ozsWizzard 06-03-2013 15:50:28

Yo tiro por la tangente.

Yo, a veces, tengo dos métodos de clase, dos procedimiento llamados "Instanciar" y "Liberar", en ellos hago lo siguiente:
Código Delphi [-]
class procedure TObj.Instanciar(var Param: TParam; var pObj; TObj);
begin
    Liberar(pObj);

    pObj := TObj.Create(Param);
end;

class function TObj.Liberar(var pObj: TObj);
begin
   if Assigned(pObj) then
      FreeAndNil(pObj);
end;
A esta forma de trabajar, para que se parezca a la tuya bastaría con cambiar el "Instanciar" y realizar lo siguiente

Código Delphi [-]
class procedure TObj.Instanciarr(var Param: TParam; var pObj; TObj);
begin
    Liberar(pObj);

    if TObj.ValidarParam(Param) then //Siendo ValidarParam una función de clase de tipo booleana
          pObj := TObj.Create(Param);
end;

Se me olvidaba la llamada:
Código Delphi [-]
begin
   TObj.Instanciar(Param, Obj);
end;

La opción "TryCreate" no me parece mal tampoco.

Neftali [Germán.Estévez] 06-03-2013 15:55:06

No quería entrar en el comportamiento, pero a mi también me parece algo extraño el que al llamar a un Create, el constructor no cree nada y devuelva un nil. Además sin dar ningún otro "síntoma".

Es decir, si igualmente después del Create se tiene que preguntar si se ha creado algo, veo más natural lo que comenta David. Si hay algún problema levanto excepción y listo. Si hay que acabar preguntando (o haciendo algo), me "suena" más natural el tema de la excepción.

Si al crear hay algún problema, parece lógico avisare de ello.

ozsWizzard 06-03-2013 16:07:09

Bueno, yo no he querido entrar tampoco en ese tema y mucho menos en si es necesario o no avisar de que ha habido un problema, se me ocurren ejemplo prácticos del porqué.

Vamos a verlo de la siguiente forma:
  1. Tengo un objeto con varios objetos dependientes
  2. En el Destroy de ese objeto contenedor tengo el siguiente código
    Código Delphi [-]
     
    destructor TContenedor.Destroy;
    begin
       for i := 0 to ListaObjetos.Count - 1 do
       begin
          if Assigned(ListaObjetos[i]) then ListaObjetos[i].Free;
       end;
    end;
  3. cada objeto contenido tiene una misión en base a si se crea o no; ejemplo: muestra un edit si se crea o no lo muestra en caso contrario

En definitiva, si te pones a buscar caso prácticos, seguro que alguno se encuentra.

egostar 06-03-2013 16:08:51

Hola

Según la lógica yo lo nombraría

Código Delphi [-]
Obj := TObj.TryOrNil (Param);

Saludos

ozsWizzard 06-03-2013 16:16:01

En todo caso "CreateOrNil"... aunque me sigue gustando más "TryCreate". A menos que yo traduzca mal el "try"

mamcx 06-03-2013 17:07:30

El nombre mas comun que he visto en varios lenguajes es
Código:

getOrNone(param)
O si te gusta al estilo sql
Código:

ifcreate('param','defaultValue)(param)
.

Chris 06-03-2013 23:18:13

Realmente la forma de crear el objeto no es consistente con la práctica en Delphi. No es que sea malo romper con la práctica, más si ésta no es tan buena. Sino que puedes crear incosistencias en tu código. Pero la forma que propones es la utilizada por Python más o menos. Pero en Python, si un parámetro no valida se genera una excepción.

Con respecto al nombre de "Make", el verbo es muy general y ambiguo. En lo personal me quedaría con el Create.

Saludos!

Al González 07-03-2013 01:30:55

Muchas gracias por sus valiosas respuestas.

He tenido la sensación de estar enfocando mal el problema, pero algo me dice quizá no voy tan mal. Elevar excepciones desde el interior de un constructor es algo normal cuando no están dadas las condiciones estrictamente necesarias para que la instancia exista. Pero a veces la instancia puede o no puede existir, sin que lo último amerite generar un error o aviso.

Hice un ejemplo un poquitín menos "abstracto":
Código Delphi [-]
type
  TXFile = Class
    Constructor Create (Const Path :String);
    Class Function Make (Path :String) :TXFile;
  End;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    XFile1, XFile2, XFile3 :TXFile;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Constructor TXFile.Create (Const Path :String);
Begin
  // ...
End;

Class Function TXFile.Make (Path :String) :TXFile;
Begin
  If Not FileExists (Path) Then  // Si el archivo indicado no existe
  Begin
    // Intentamos con uno de respaldo
    Path := 'C:\Respaldos\' + ExtractFileName (Path);

    If Not FileExists (Path) Then  // Si el respaldo tampoco existe
    Begin
      Result := Nil;  // No hay archivo con ese nombre, situación aceptable
      Exit;
    End;
  End;

  Result := Create (Path);
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
  { Sin el método TXFile.Make (o una función que haga lo mismo que Make),
    este bloque de código sería más grande: }
  XFile1 := TXFile.Make ('C:\Hugo.x');
  XFile2 := TXFile.Make ('C:\Paco.x');
  XFile3 := TXFile.Make ('C:\Luis.x');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  XFile1.Free;
  XFile2.Free;
  XFile3.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // ...

  If XFile1 <> Nil Then
    // ...

  // ...

  If XFile2 <> Nil Then
    // ...

  // ...

  If XFile3 <> Nil Then
    // ...

  // ...
end;

Lo de Make fue por buscar un sinónimo de Create, algo que, quizá (y ahí tengo mi mayor duda) pudiera llegar a ser acuñado y con el tiempo dejar de sonar confuso o ambiguo. Una palabra que "insinúe" una acción semejante a la del constructor, pero que al mismo tiempo se diferencie de éste, entendiéndose que podemos obtener un Nil si cierta condición (que podría estar documentada) no se cumple en la llamada a ese método especial.

«Oh, mire compañero, la clase tiene método Make, hay que usarlo en esta parte del programa. Según dice aquí, devuelve Nil cuando...»

Me empieza a gustar el nombre TryCreate que propusieron en mensajes anteriores. TryOrNil se entiende también, pero se pierde un poco el sentido de "crear".

Otro camino es que este tipo de métodos se definan con nombres más explícitos y acomodados a cada clase y situación en particular, con lo cual ya no tendríamos una candidatura a estándar.

Y bueno, también está la opción de crear una función normal o de otra clase, que haga la tarea, pero creo que es más correcto que la propia clase se encargue de validar o verificar lo que a la clase concierne. ¿No creen?

Bueno, a alguna conclusión habremos de llegar entre todos. :)

¡Saludos!

roman 07-03-2013 03:33:30

¿Build?

// Saludos

roman 07-03-2013 03:39:42

Cita:

Empezado por Al González
Y bueno, también está la opción de crear una función normal o de otra clase, que haga la tarea

Podría ser algo así:

Código Delphi [-]
TXFile = class
  ...
end;

TXFileFactory = class
public
  [class] function Create(Path: String): TXFile;
end;

// Saludos

Al González 07-03-2013 08:33:41

Gracias Román. :)

Una hora más temprano que ayer, pongo una breve lista de posibles nombres:
  • Make
  • TryCreate
  • Build
  • CreateBy
  • Produce
  • Generate
  • Construct
Me estoy inclinando por Produce. Make da la simple idea un tanto vaga de "hacer algo", mientras que Produce es más concreto y sugiere la "construcción de algo" (un objeto) y a la vez sugiere que "produce un resultado" (que podría ser Nil).

Neftali [Germán.Estévez] 07-03-2013 09:06:10

Creo que alguien ha comentado el CreateOrNil. No suena muy bien, pero es descriptivo 100%. Recordemos que Delphi ya cuenta con un FreeAndNil.
Es por si ya te estabas decidiendo... Para que tengas un poco más de dudas... :D:D:D

Delphius 07-03-2013 14:50:25

Hola Al, creo que el concepto o palabrita que buscas es Materializar, o Materialize en inglés.
Este término se emplea en los frameworks de persistencia, y a mi ver Materializar no es propio de la persistencia en bases de datos, sino en su forma abstracta. Asi que no veo el porqué no aprovecharlo.

Ahora, respecto a la utilidad del código, si me lo permites quisiera preguntar algo ¿Donde o que clase "cliente" lo utilizará o invocará al método en cuestión? ¿O es que no existe un lugar concreto donde usarlo?
Como seguramente ya has visto un diseño de resultado booleano (objeto|nil) llevará a que al final se deba hacer una comprobación posterior, o bien hacer uso de try.
Ahora bien, si en verdad nil es un resultado realmente válido (tiene un significado real y está aceptado en el contexto) y no deja al objeto que cumple el rol del creador en un estado inconsistente no hay problemas. Pero si este nil en realidad no responde a un resultado aceptable y tolerable lo correcto sería que no se devolviese nil sino que se eleve una excepción. Como nombre podría sugerir EUnmaterializedException o ETXFileUnmaterializedException.

De este modo en donde se lo invoque simplemente se trabaja directamente con try y poder volver a un estado de calma sin estar alterando el flujo principal del código.

Por otro lado, Al... me huele a que estás diseñando una Fábrica. ;)

Saludos,

ozsWizzard 07-03-2013 14:51:53

Cita:

Empezado por Neftali (Mensaje 456160)
Creo que alguien ha comentado el CreateOrNil. No suena muy bien, pero es descriptivo 100%. Recordemos que Delphi ya cuenta con un FreeAndNil.
Es por si ya te estabas decidiendo... Para que tengas un poco más de dudas... :D:D:D

He sido yo ;)

Tampoco ha puesto el nombre que sugerí de "Instanciar", no le habrá gustado, jeje.

Por otra parte, con la forma en la que crea los objetos, este trozo de código que ha puesto Al, petaría (daría una excepción):

Código Delphi [-]
procedure TForm1.FormDestroy(Sender: TObject);
begin
  XFile1.Free;
  XFile2.Free;
  XFile3.Free;
end;

Delphius 07-03-2013 15:00:26

Cita:

Empezado por ozsWizzard (Mensaje 456176)

Por otra parte, con la forma en la que crea los objetos, este trozo de código que ha puesto Al, petaría (daría una excepción):

Código Delphi [-]
procedure TForm1.FormDestroy(Sender: TObject);
begin
  XFile1.Free;
  XFile2.Free;
  XFile3.Free;
end;

¿Donde está el problema? Free es un método seguro. Si las instancias XFile1, XFile2 y XFile3 no fueran válidas (nil) Free lo detectará y no intentará liberar algo que ya fue liberado o bien nunca fue creado.

Un objeto se crea totalmente o no se crea nada. No hay términos medios.

Saludos,

ozsWizzard 07-03-2013 15:20:28

Tienes, razón, cuando es nil no peta, sorry.

Entonces me he molestado en hacer una Liberar que no sirve pa na... :(

Ahora, si se intenta liberar algo que nunca se creó pero que no está iniciado a nil, sí que peta. Lo siguiente peta.

Código Delphi [-]
procedure TFrmPruebas.Button1Click(Sender: TObject);
var
   q: TSqlQuery;
begin
   q.Free;
end;

dec 07-03-2013 15:38:33

Hola,

Me surgen muchas dudas con este asunto. Dudas que no van a ningún sitio, avisados quedáis. Al cabo de darle algunas vueltas me pregunto, ¿puede un objeto ser "nil"? Y me respondo: tal vez sí, cuando busquemos un objeto que puede o no haber sido creado, pero, no, si de lo que se trata es de crear dicho objeto. Es decir, yo veo el siguiente código "válido" y de hecho he escrito mucho código de esta forma:

Código Delphi [-]
var
  module : TMyModule;
begin
  module := MyModules.GetModule( 123 );  

  if module <> nil then
  begin
    // Module is a valid object for us
  end
  else
  begin
    // We can't found a module with ID 123
  end;
end;

En el código de arriba, puesto que no estamos creando un objeto sino tratando de asignar uno (posiblemente) existente, creo que el "nil" tiene toda la lógica, puesto que el método "GetModule" retornará "nil" si no puede encontrar un objeto o el objeto mismo.

Ahora bien, si de lo que se trata es de saber si un objeto se puede crear, correctamente, en base a ciertos argumentos, entonces yo escribiría un código similar a este:

Código Delphi [-]
var
  params : string;
  module : TMyModule;
begin
  params := 'My params';

  module := TModule.Create( params );

  if module.HasValidParams() then
  begin
    // We have a valid object here, with the right params
  end
  else
  begin
    // We have a valid object here, but with wrong params
  end;
end;

¿Se entiende por dónde voy? Nosotros pasamos los parámetros conque contemos (tal vez sean válidos, tal vez no lo sean) al constructor de nuestro objeto, y, este, por ejemplo, proporciona un método "HasValidParams", que, podremos usar para comprobar si el objeto de hecho se ha creado en condiciones... con los parámetros correctos.

De esta forma nos olvidamos del "nil", nos olvidamos con un método de clase que nos retorne una instancia del objeto mediante ciertos parámetros (¿podré usar el constructor sin parámetros o los necesitaré también?) y es el propio objeto, conocedor de los parámetros que necesita, quien nos dirá si está listo para usarse o no.

¿Cómo lo veis? ;)

Delphius 07-03-2013 16:02:38

Muy bien dicho David, has ido a lo que yo quería hacer llamar la atención. Como tu has dicho:

Cita:

creo que el "nil" tiene toda la lógica,
Y yo por algo había comentado antes:

Cita:

Ahora bien, si en verdad nil es un resultado realmente válido (tiene un significado real y está aceptado en el contexto)
Al, es primordial entender ¿que significa para ti que el objeto sea nil? ¿Tiene algún propósito?

Porque como lo ha dejado en claro en el ejemplo David, si la idea es garantizar o evaluar si hay cierta consistencia, quien tiene la información para hacerlo es el creador o el objeto en si mismo. Esto conduce a que para hacer algo entonces se puede disponer de un método que lo compruebe, y ahora si ya en base a estos resultados decidir que o no hacer.

Y como dije antes, si nil no es una opción a considerar sino una situación fuera de lo esperado los lineamientos de la OO indican que lo sano es elevar excepción.

Saludos,

dec 07-03-2013 16:44:28

Cita:

Empezado por Delphius (Mensaje 456191)
Muy bien dicho David, has ido a lo que yo quería hacer llamar la atención. Como tu has dicho:



Y yo por algo había comentado antes:



Al, es primordial entender ¿que significa para ti que el objeto sea nil? ¿Tiene algún propósito?

Porque como lo ha dejado en claro en el ejemplo David, si la idea es garantizar o evaluar si hay cierta consistencia, quien tiene la información para hacerlo es el creador o el objeto en si mismo. Esto conduce a que para hacer algo entonces se puede disponer de un método que lo compruebe, y ahora si ya en base a estos resultados decidir que o no hacer.

Y como dije antes, si nil no es una opción a considerar sino una situación fuera de lo esperado los lineamientos de la OO indican que lo sano es elevar excepción.

Saludos,

Yo apunté también lo propio (lo siento Delphius, no leí tus anteriores mensaje), pero, ¿serviría de algo lanzar la excepción en el constructor del objeto? Me refiero a si tiene sentido en el contexto en que nuestro amigo Al trabaja. Además no me queda muy claro el uso de excepciones tal que así:

Código Delphi [-]
try
  obj := TMyObject.Create();
except
  on E : Exception do
  begin
    // Manejamos la excepción, pero,...
  end;

  // ¿qué pasa con el código situado aquí debajo?

end;

Al González 07-03-2013 20:21:54

Cita:

Empezado por Neftali (Mensaje 456160)
Es por si ya te estabas decidiendo... Para que tengas un poco más de dudas... :D:D:D

Ahora mismo mis dudas es si la discusión estilo narco / mafia que se desarrolla justo afuera de mi ventana tendrá repercusiones en nuestra vida. Y si lograremos encontrar un sitio más económico (y seguro) antes de que la renta venza. :(

:)

--------------

Volviendo al tema, es algo que implementaré en un par de clases de GH Freebrary. Cuando esté listo lo subiré y ya me dirán si estoy haciendo bien las cosas. :o

Descarto los nombres que llevan la palabra Create o Instantiate porque son demasiado "fuertes" en el sentido de que parece que forzosamente se creará un objeto. Y lo del AndNil / OrNil los veo como recursos léxicos baratos; lo identificadores debieran llevar lo menos posible preposiciones, conjunciones y similares (hago uso de ellos en contadas ocasiones).

Saludos.

Delphius 07-03-2013 20:34:22

Cita:

Empezado por dec (Mensaje 456200)
pero, ¿serviría de algo lanzar la excepción en el constructor del objeto? Me refiero a si tiene sentido en el contexto en que nuestro amigo Al trabaja. Además no me queda muy claro el uso de excepciones tal que así:

Código Delphi [-]
try
  obj := TMyObject.Create();
except
  on E : Exception do
  begin
    // Manejamos la excepción, pero,...
  end;

  // ¿qué pasa con el código situado aquí debajo?

end;

Pues, por eso dije que lo sano según OO sería arrojar una excepción. Pero el contexto/uso/modo de esta problemática como que me rompe los moldes y no ando seguro.
Respecto al código de ejemplo, me hago la misma pregunta que tu. ¿Que pasa allí abajo? ;)

Al, no es que esté mal o bien... sino que es diferente. Si no es mucha molestia, ¿Podrías concretar un poco más? Y como dije antes... me gustaría saber que significaría un resultado nil. Creo que ello ayudaría a entender mejor el panorama y ver alternativas.

Aunque admito que mi ración de neuronas despiertas del día son escasas... tengo un diagrama de estados para una clase que acaparó demasiados recursos y mi cerebro no ha logrado restablecer la electricidad :o :p

Saludos,


La franja horaria es GMT +2. Ahora son las 01:48:46.

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