¿Y usando tipos "Record"?
No mataríamos moscas a cañonazos, como con las clases, y te proporciona muchas características similares.
Por cierto, excelente artículo de Cary Jensen sobre esto en http://caryjensen.bl...for-record.html
Un saludo
Si dispusiera de Delphi 2005/6 en adelante podría hacer lo que se comenta en dicho artículo; aunque igual sería matar moscas a cañonazos. Y sinceramente no veo la utilidad de dotar a un tipo record de propiedades y métodos... para tal caso mejor declarar una clase. Me hace acordar de como crear clases en C.
En el caso de que no siempre haga falta usar los valores devueltos en esos parámetros, puedes, en lugar de pasarlos por referencia, pasar punteros. Esto te permite usar valores por defecto, valor nulo.
Con esto la sintaxis es mas simple en algunas llamadas.
Saludos.
Me interesa esta posibilidad escafandra. ¿donde podría ver algún ejemplo de uso? Tu sabes que yo le huyo a los punteros y nos uso a menos que se me haga necesario
Hola.
¿ Porqué no cambias los procedures por functions y devuelves esos valores (error/estado/...) en la función ?. Cuando no te interese ese resultado, podrás seguir usando la llamada como si fuese un procedure.
Fue lo primero que se pasó por la cabeza. Hacer que sean funciones, pero en cuanto empecé a seguir implementando algunas de las funcionalidades me quedó un sabor a "algo no está bien" y que algunas de estas funciones deberían tener nombre y comportamiento de procedimientos. Asi es que luego pasé al enfoque de parámetros por referencia y convertí a esas "funciones procedure" en procedure con el parámetro adecuado. Y así es como ahora llegué a esta situación.
Otra cosa que podría ser útil es la sobrecarga de parámetros. Puedes tener dos definiciones de tus procedimientos, una con parámetros de error/estado/... y otra sin ellos, de manera que podrás utilizar una u otra en función de que lo necesites o temas que puedan aparecer errores.
Saludos.
Ya algunos están sobrecargados amigo. Y no es posible evitar de esta forma los parámetros de control, ya sea que se utilice cualquiera de las funciones o procedimientos sobrecargados. Por naturaleza del problema y diseño todas las versiones sobrecargadas necesitan regresar este valor para control.
Es decir tengo:
procedure HacerEsto(Param1, Param2, .... var ErrorCode: integer); overload;
procedure HacerEsto(Param1: TParam1; var ErrorCode: integer); overload;
Podrías tener un TStringList (o similar) que sea global, y donde al llamar a tu function (nada de procedures, te tocaría convertirlos todos a function), si hay problemas, esta añadiría un item y en él escribe su "error code" o lo que sea, y te devuelve como respuesta el indexof de ese elemento. Si no hay error, te devuelve un -1 por ejemplo.
Sería como tener una pila de errores y poder leer el que corresponde a tu llamada a las APIs.
Ojo si las llamadas son desde distintos hilos, si todos los hilos tocan el stringlist a la vez vas a tener problemas!
Otro detalle es que cada "llamada" debería hacer un delete del item una vez leido el error code, o bien eliminar el item[0] hasta que no pases de 100 items para evitar que se coma la memoria el stack de errores.
Estuve pensando en algo parecido a esa lista de errores/estado que describes. Aunque no con la forma de funciones para que regresara el índice, ya que me quería evitar las versión en funciones. Ahora me doy cuenta de que es fundamental de que se me permita regresar el índice para poder leer el error adecuado a la llamada producida.
El problema está en que habrá ocasiones en que dos o más procedimientos o funciones se realicen en "simultáneo" y cada uno por tanto requiera leer su valor de control con lo que se pisan los resultados y el último valor será el del último método en ejecutarse.
¿Utilizas varios Threads? porque si no lo haces no hay problema, solo tendrías que llamar la función "GetLastErrorCode" justo después de cada función, al igual que se utiliza la API GetLastError de windows.
No utilizo hilos... no por el momento y en esta versión; aunque no se descarta su uso.
Justamente inspirado en esa API Windows es que luego empecé a considerar esta alternativa pero me quedó la duda de si no tendré problemas por varias llamadas rápidas y que en ocasiones se realizan en forma "asincronizada".
Te explico, gracias al patrón Observador es que propago llamadas desde una clase a otras en cuanto cambia algo; gracias al poder de los eventos. Resulta ser que luego la clase que "escucha" estos eventos al ser notificada decide si le toca o no hacer algo. Ese algo en ocasiones implica hacer llamadas y uso por tanto de esta API.
Se podría distinguir 3 grupos de clases clientes (que vendría a ser parte del dominio) cada grupo tiene su función. Estos grupos se apoyan en unas clases Sujetos que son quienes les notifica los cambios y hacen uso de la API. Cuando algo cambia en un sujeto deberá propagar notificar a los observadores de los grupos registrados para que actualicen su "estado". Vendría a ser algo así:
+--------+ +--------+ +--------+
| Grupo1 | | Grupo2 | | Grupo3 |
+--------+ +--------+ +--------+
^ ^ ^ ^
| | | |
| +------+ | | +------+ |
+-->| Suj1 |<--+ +-->| Suj1 |<--+
+------+ +------+
^ ^
| |
| +-----+ |
+-->| API |<---+
+-----+
El diseño es tan armónico que un cambio en las condiciones del grupo1 lleva a cambios que se deben notificar hacia el 2, luego desde el grupo 2 al grupo 3. Finalmente el grupo 3 puede operar tranquilamente y no tener que notificar nada al resto a menos que se cumpla una condición. En cuanto se detecta el caso debe realizar operaciones. Esto al final se traduce a que se le notifique al sujeto1 de unos cambios y debe proceder a nuevas llamadas y notificaciones para el grupo 1, y así se produce de nuevo un nuevo ciclo.
Hagamos de cuenta que es un círculo:
+--------+ +--------+ +--------+
| Grupo1 |---->| Grupo2 |---->| Grupo3 |---+
+--------+ +--------+ +--------+ |
^ | ^ |
| | | |
| +---+ |
| |
+---------------------------------------+
Técnicamente el grupo 2 también tiene un ciclo propio para que luego de una confirmación de todo su proceso interno se notifique al grupo 3. Pero aquí lo he omitido por simplicidad para explicar la condición inicial.
Inicialmente tiene lugar solamente el grupo1, al confirmar sus operaciones, el grupo 2 puede trabajar... mientras tanto el grupo 1 se "queda a la espera" de novedades (que el grupo 3, gracias a mediadores fuera de esta discusión le hará saber). Una vez que 2 confirma tiene lugar el grupo 3, y ahora el grupo 2 también está a la espera. Y finalmente el grupo 3 puede operar sin problemas.
El asunto es que llegado al punto 3, pueden darse casos en que el grupo 2 pueda recibir notificaciones y volver a realizar sus operaciones sin que tenga que pasar por el grupo 1, y estos cambios no necesariamente van a afectar a que 3 tenga que actualizar sus operaciones (ya que de hecho, solo toma lo procesado por el grupo 2). De este modo de allí que el grupo 2 y 3 hagan uso de la API en "simultáneo". Solo en casos especiales en que el grupo 3 detecta es que tiene lugar un nuevo ciclo completo:
Entonces los ciclos, son:
+--------+ +--------+ +--------+
| Grupo1 |---->| Grupo2 |---->| Grupo3 |---+
+--------+ +--------+ +--------+ |
^ | ^ | ^ |
| | | | | |
| +---+ +---+ |
| |
+---------------------------------------+
Se han omitido los sujetos que hacen de intermediadores entre cada grupo a fin de que el "dibujo" se vea más claro. Naturalmente es que estos sujetos son los encargados de ir dando aviso de un grupo a otro y trabajan en forma directa con la API.
Entonces me asaltó la duda de si estos sujetos que actúan con la API podrán trabajar sin problemas sin pisarse la cola mutuamente. ¿Tu dices que no debería haber problemas? De ser así pruebo este enfoque y me voy a por eso directamente y me dejo de llorar por la cantidad de parámetros... de última veo la posibilidad de descomponer más a las funciones y procedimientos y de ese modo reducir la cantidad de parámetros.
Otro motivo por el cual utilizo esta forma de API es que es de propósito general. No es algo especializada y única para este problema... dispone de las herramientas para varias aplicaciones.
Son los sujetos que actúan con ella quienes ya ofrecen una interfaz adecuada al resto del dominio.
Y si los utilizas tampoco habría problemas, solo mas trabajo tendrías que guardar las variables de tal manera que fueran accesibles a todas las funciones pero con diferentes valores para cada thread.
Aquí un ejemplo en C
http://msdn.microsof...7(v=vs.85).aspx
ha... ha... hachús..... snif... snif ¿Alguien tiene pañuelo? Ver C me enfermó
Saludos,