PDA

Ver la Versión Completa : Ese día llegó


Al González
16-11-2016, 07:28:11
He liberado la primera parte de mi biblioteca de clases para versiones modernas de Delphi, en un sitio Web famoso para proyectos de software libre.

Es una versión beta, todas las unidades compilan en Delphi XE7.

https://github.com/algonzalez74/GHFreebrary

Bienvenidas las contribuciones. :)

Neftali [Germán.Estévez]
16-11-2016, 09:41:38
Gracias Al.
#:-)##:-)##:-)#

Casimiro Notevi
16-11-2016, 10:46:08
Un gran paso adelante... ^\||/

jhonny
16-11-2016, 15:55:54
Que alegría saber de este lanzamiento :), te felicito y agradezco Al.

AgustinOrtu
16-11-2016, 16:28:07
Me uno a las felicitaciones. Vamos a pegar un vistazo si señor!

ecfisa
16-11-2016, 19:38:45
Gran trabajo, ¡ Felicitaciones ! ^\||/

Un abrazo :)

newtron
17-11-2016, 09:28:50
Amigo Al.

Gracias por compartir tu trabajo. ^\||/

dec
17-11-2016, 10:43:43
Hola a todos,

¡Me uno a las felicitaciones Al! :)

movorack
17-11-2016, 13:47:04
Muchas gracias Al por compartir tu conocimiento y estas librerías con todos nosotros.

AgustinOrtu
18-11-2016, 18:53:22
Seria realmente genial iniciar algo como esto (http://www.clubdelphi.com/foros/showthread.php?t=83841) con la nueva biblioteca

AgustinOrtu
18-11-2016, 19:56:15
Hola nuevamente Al

Estuve explorando un poco el codigo, pero aun no he puesto en marcha ninguna prueba

Solamente tengo un par de comentarios para hacerte:

- Me alegra que uses identificadores calificados. A mi tambien me gusta hacerlo y creo que crear bibliotecas publicas es una buena forma de impulsar al resto a que haga lo mismo. Solamente hay una pequeña diferencia en como lo hago yo; yo prefiero seguir la convencion que esta adoptando poco a poco Firemonkey, en la cual, el prefijo para los elementos del tipo enumerado ya no se usa

Por ejemplo, de GHF.Sys, linea 528


TDirectionSide = (eSource, eDest);


Esto nos lleva a escribir codigo asi:


procedure Foo(const Direction: TDirectionSide);
begin
if Direction = TDirectionSide.eSource then
begin
//
end;
end;


Yo creo que el prefijo que historicamente se uso en Delphi (pensando tambien en TAlignLayout --> alClient, alTop, etc) no es necesario si se usan identificadores calificados y "ensucia" el codigo fuente.

Otro detalle que creo que es importante, veo que en tus unidades siempre activas la directiva de compilacion SCOPEDENUMS (http://docwiki.embarcadero.com/RADStudio/en/Scoped_Enums_(Delphi))

Ahora me entro la curiosidad, pero yo creo que lo mas seguro es compilar nuestros tipos enumerados con la directiva y luego volver a ponerla a OFF que es su valor por defecto. Es decir, asi es como yo declaro los tipos enumerados:

{$SCOPEDENUMS ON}
/// <summary> The diferent scopes that a Token is allowed to operate on </summary>
TTokenScope = (
/// <summary> The Token may Read data </summary>
Read,
/// <summary> The Token may Write data </summary>
Write,
/// <summary>
/// The Token may operate on a Offline basis, that is, the user grants permission once and then the bearer may
/// request a refresh without explicitly asking the user
/// </summary>
Offline_Access
);
{$SCOPEDENUMS OFF}

Esto me asegura que si o si se deba prefijar el tipo para poder utilizar alguno de los valores, que es el efecto deseado

- Otra recomendacion es el uso de regiones (http://docwiki.embarcadero.com/RADStudio/en/Regions) para hacer el codigo mas legible. Las regiones te permiten [plegar (http://docwiki.embarcadero.com/RADStudio/en/Using_Code_Folding)?] porciones del codigo y denotarla con un nombre, para hacer mas facil la navegacion dentro de la unidad. Es mas largo hacer scroll en una unidad larga como por ejemplo las GHF.Sys y GH.SysEx. Tambien creo que es una buena idea usar una region para la licencia, que ocupa su buena porcion de espacio

- El ultimo punto es el uso de la documentacion XML. Esta es una de las ultimas practicas que he adoptado, y ya me he acostumbrado. Consiste en documentar el codigo de forma tal que pueda ser util al momento de que el usuario use tu biblioteca, y no tenga que tener un manual de referencia para consultar. Esta documentacion XML se adjunta en la ventana que aparece cuando Delphi nos muestra cuales y que tipo de parametros recibe un metodo, el retorno de una funcion, etc

Si hoy escribo alguna clase, metodo, funcion, tipo, lo que sea, sin incluir la documentacion XML, me siento mal conmigo mismo (es similar a tu comentario (https://www.clubdelphi.com/foros/showpost.php?p=503862&postcount=2) cuando hablamos de esto). De hecho en muchas ocasiones me ha pasado que es dificil explicar que es lo que deberia hacer el metodo en cuestion, y es cuando detecto un error de diseño que debe ser refactorizado incluso antes de escribir codigo; tambien existe el caso de que no se me ocurre como escribir el codigo, pero al escribir la documentacion luego se hace mas facil la implementacion

El efecto logrado es el siguiente:


unit Vcl.WinControl.Helper;

interface

uses
Vcl.Controls;

type
{$REGION 'TWinControlHelper'}
TWinControlHelper = class helper for TWinControl
public
/// <summary> Intenta darle foco al control; devuelve True si tuvo exito, False en caso contrario </summary>
/// <remarks> Este metodo captura y controla excepciones </remarks>
function TrySetFocus: Boolean;
end;
{$ENDREGION}


http://thumbs.subefotos.com/b18ec1e114fa71ffcda18f33b142e74co.jpg (http://subefotos.com/ver/?b18ec1e114fa71ffcda18f33b142e74co.png)

http://thumbs.subefotos.com/9557608ac97d5937572da25dc96afd00o.jpg (http://subefotos.com/ver/?9557608ac97d5937572da25dc96afd00o.png)


Las ultimas vesiones de Delphi, en sus bibliotecas mas nuevas, escriben esta documentacion en linea y me ha ayudado mucho, por ejemplo la unidad REST.Json


TJson = class(TObject)
public
/// <summary>
/// Converts any TObject descendant into its Json representation.
/// </summary>
class function ObjectToJsonObject(AObject: TObject; AOptions: TJsonOptions = [joDateIsUTC, joDateFormatISO8601]): TJSOnObject;
/// <summary>
/// Converts any TObject decendant into its Json string representation. The resulting string has proper Json
/// encoding applied.
/// </summary>
class function ObjectToJsonString(AObject: TObject; AOptions: TJsonOptions = [joDateIsUTC, joDateFormatISO8601]): string;

/// <summary>
/// Encodes the string representation of a TJSONValue descendant so that line breaks, tabulators etc are escaped
/// using backslashes.
/// </summary>
/// <example>
/// {"name":"something\else"} will be encoded as {"name":"something\\else"}
/// </example>
class function JsonEncode(AJsonValue: TJsonValue): string; overload;
end;

Al González
20-11-2016, 09:39:28
Hola Agustín. Me da mucho gusto notar el gran interés que muestras. :)

Intentaré responder a todas tus inquietudes, comenzando por esta:
Seria realmente genial iniciar algo como esto (http://www.clubdelphi.com/foros/showthread.php?t=83841) con la nueva biblioteca
Muchos de aquellos ejemplos todavía tienen valor, sólo que algunos métodos cambiaron de lugar o de nombre. No me opondré si inicias otros hilos para dar a conocer nuevos ejemplos con lo que vayas descubriendo. Incluso puedes empezar tomando el ejemplo comparativo que acabo de poner en el Readme (https://github.com/algonzalez74/GHFreebrary/blob/master/README.md).

Saludos.

Al González.

Al González
20-11-2016, 20:23:46
Me alegra que uses identificadores calificados. A mi tambien me gusta hacerlo y creo que crear bibliotecas publicas es una buena forma de impulsar al resto a que haga lo mismo
Sigamos impulsándolo (https://twitter.com/algonzalez74/status/707979411920801792). ;)

prefiero seguir la convencion que esta adoptando poco a poco Firemonkey, en la cual, el prefijo para los elementos del tipo enumerado ya no se usa [...] creo que el prefijo que historicamente se uso en Delphi no es necesario si se usan identificadores calificados y "ensucia" el codigo fuente.
También iba a adoptarla pero luego recordé que, con los record helpers, casi cualquier tipo de datos (incluyendo los enumerados) puede tener propiedades, métodos, otras constantes, etcétera. Quitar por completo el prefijo de las constantes enumeradas supone un problema a la hora de que nosotros leemos una expresión como "TFoo.Bar". ¿Es Bar una de las constantes enumeradas que definen el tipo o es otra cosa? En cambio "TFoo.eBar" no sólo permite inferir qué tipo de elemento es eBar (una constante enumerada), sino que por relación lógica permite determinar también qué es TFoo (un tipo enumerado). Dentro de otras estructuras, como las clases, hay variedad de elementos que no es costumbre ni muy útil distinguir mediante un prefijo. Yo empleo el prefijo sólo en casos especiales. Y uno de ellos es el de las constantes que aparecen en la declaración de un tipo enumerado, porque nunca sabes cuándo tú o alguien más le añadirá propiedades o métodos mediante un ayudante.

en tus unidades siempre activas la directiva de compilacion SCOPEDENUMS (http://docwiki.embarcadero.com/RADStudio/en/Scoped_Enums_(Delphi)) [...] creo que lo mas seguro es compilar nuestros tipos enumerados con la directiva y luego volver a ponerla a OFF que es su valor por defecto.
Eso es lo normal con otras directivas de compilación locales. Sin embargo, pongo {$ScopedEnums On} desde el inicio de cada unidad para asegurarme de que todos los tipos enumerados que ella declare serán utilizados desde el exterior de forma calificada, sin excepción. Cuando el autor está convencido de la buena práctica que antes mencionamos, no hay riesgo alguno en poner esa directiva en On para toda la unidad.

Otra recomendacion es el uso de regiones (http://docwiki.embarcadero.com/RADStudio/en/Regions) [...] Las regiones te permiten [plegar (http://docwiki.embarcadero.com/RADStudio/en/Using_Code_Folding)?] porciones del codigo
Tomo tu recomendación. Conozco lo útil que es la directiva $Region, y ya uso algunas, como la {$Region 'Error messages (ermXXX)'} presente en varias unidades. Aunque admito que sería bueno "regionizar" más bloques. Voy a trabajar en ello. :) ^\||/

creo que es una buena idea usar una region para la licencia
Cierto, lo haré también. ^\||/

[...] uso de la documentacion XML. Esta es una de las ultimas practicas que he adoptado, y ya me he acostumbrado. Consiste en documentar el codigo de forma tal que pueda ser util al momento de que el usuario use tu biblioteca, y no tenga que tener un manual de referencia para consultar. Esta documentacion XML se adjunta en la ventana que aparece cuando Delphi nos muestra cuales y que tipo de parametros recibe un metodo, el retorno de una funcion, etc [...] me ha pasado que es dificil explicar que es lo que deberia hacer el metodo en cuestion, y es cuando detecto un error de diseño que debe ser refactorizado incluso antes de escribir codigo; tambien existe el caso de que no se me ocurre como escribir el codigo, pero al escribir la documentacion luego se hace mas facil la implementacion
Esto tampoco me es indiferente. La pregunta es ¿cómo hacer una documentación "in-line" sin "ensuciar" el código? Hasta ahora no me convencen las convenciones y herramientas que he visto (si bien no he visto mucho, aclaro). Este punto hay que seguir estudiándolo.

AgustinOrtu
21-11-2016, 01:05:34
Lamentablemente no puedo usar la biblioteca ni en Delphi 2010 ni 10.1 Berlin, debido a errores de compilacion

Voy a ver si puedo ir solucionandolos poco a poco para poder probar algo

Saludos!

Al González
21-11-2016, 02:53:32
Lamentablemente no puedo usar la biblioteca ni en Delphi 2010 ni 10.1 Berlin, debido a errores de compilacion

Voy a ver si puedo ir solucionandolos poco a poco para poder probar algo

Muchas gracias, Agustín. Acá me están haciendo un trámite para tener más libertad con los instaladores. Deseo poder dedicar tiempo a la adaptación para diferentes versiones. De hecho sería bueno abrir una nueva encuesta (http://www.clubdelphi.com/foros/showthread.php?t=89334) para ver cómo se está moviendo el universo de usuarios.

Hoy, con el repositorio (https://github.com/algonzalez74/GHFreebrary), será más fácil que otros programadores se involucren con el proyecto.

Te adelanto que el problema para compilar en Seattle y Berlin tiene que ver principalmente con cierta puerta trasera que permitía a una clase genérica acceder a los campos privados de su clase padre. Yo la utilicé preguntando primero si se trataba de un bug y no encontré respuesta. Pero para el lanzamiento de Seattle cerraron esa puerta (oficialmente se reconoció como defecto). Así que hay que cambiar código para que Delphi 10 y 10.1 logren compilar un par de clases ahora incorrectas.

Saludos. :)

AgustinOrtu
21-11-2016, 02:57:12
En Berlín también está el problema de que los ayudantes ya no pueden acceder a la sección privada. Por ejemplo la unidad para Rtti de GHF no compila por eso. Y que yo sepa no hay un workaround limpio para solucionarlo. Las únicas alternativas que hay por ahí son horrendos hacks

Y mucho no puedo indagar porque con Starter no tengo código fuente

Al González
21-11-2016, 04:01:53
En Berlín también está el problema de que los ayudantes ya no pueden acceder a la sección privada.
Es lo mismo que comentaba antes. La característica o bug (según el ángulo con que se mire) estuvo presente en ayudantes y genéricos por varias versiones porque no se ponían de acuerdo sobre si era correcto o no que existiera. Al final ganó el ala conservadora, y se canceló esta facilidad por considerarse contraria al espíritu de una sección private.

Trabajaré en la adaptación en cuanto me sea posible. :)

Saludos.