Re: Initialisation dans le corps d'un paquetage
Thomas De Contes via Ada-france <[email protected]> Wed, 29 Sep 2021 05:21:26 +0200
| Newsgroups | gmane.comp.lang.ada.france |
|---|---|
| Message-ID | <[email protected]> |
Le 15 sept. 2021 à 17:45, Jean-Pierre Rosen a écrit :
> Le 13/09/2021 à 14:33, Thomas De Contes a écrit :
>> Je crois avoir trouvé la méthode pour faire ce choix :
>> Quand on est tenté de faire une initialisation de paquetage,
>> la question à se poser c'est : existe-t-il une 3ème alternative que l'initialisation de paquetage et la procédure Init ?
>> - si oui, il vaut mieux préférer la 3ème alternative,
>> - si non, il vaut mieux préférer l'initialisation de paquetage que la procédure Init, et ça n'est pas un abus.
>> Que penses tu de cette méthode ?:-)
> Oui, en fait la procédure init se justifie si on a besoin de paramètres, typiquement passer un nom de fichier pour un paquetage qui fait des logs.
Merci pour l'idée, je ne l'avais pas eue !
L'inconvénient c'est que ça oblige à avoir une variable globale,
mais c'est la moins mauvaise solution qui permette de ne pas tout chambouler le jour où je voudrai prendre en charge un fichier de configuration ! :-)
Je crois comprendre que les variables globales, même si je ne les aime pas à cause des effets de bord,
elles sont inévitables et finalement pas forcement inappropriées, dans des cas particuliers comme celui là où on traite quelque chose qui est forcément global à l'application et qui ne doit pas être multiplié dans des contextes locaux :-)
À propos :
Dans un contexte où j'essaye de faire du "code propre" et des fonctions sans effet de bord,
dans quelle mesure trouves-tu acceptable de faire une fonction qui rapporte du debug et des erreurs à logger ?
> Quoi qu'on pourrait aussi en faire un générique...
Non, là ça pose un problème de visibilité (qui me semble) insurmontable,
du fait que je ne connais le nom des fichiers de log qu'au niveau de l'application, et que j'ai besoin de générer des logs aussi dans la bibliothèque.
Sans compter le risque d'exécuter plusieurs fois l'initialisation, si on l'instancie plusieurs fois (surtout avec les mêmes paramètres).
À propos :
Il me semble qu'avec les génériques on peut réutiliser un paramètre dans un autre, mais pas avec les sous-programmes.
Pourquoi ? Il me semble bien que ça ne pose pas de problème de lisibilité ni de sécurité.
J'aurais trouvé pratique de pouvoir faire :
procedure Init (ErrorsLogFile_Name : String; DebugLogFile_Name : String := ErrorsLogFile_Name);
(et j'ai trouvé un autre cas où ça serais pratique aussi).
------------------------------------------------------------
Pour le plaisir, parce que je risque bien de ne jamais avoir l'occasion de le programmer en vrai :-)
Voilà le cas où le nom des fichiers de log est fixe, ce qui permet de tout faire à l'élaboration :
(Non testé, si ça se trouve ça ne marche pas.)
Si ça marche comme attendu,
on considère que les fichiers de log sont facultatifs, donc les erreurs de mcc.Msg.with_LogFiles.Error ne sont pas à rapporter :
mcc.Msg.Error rattrape toutes les erreurs de mcc.Msg.with_LogFiles.Error,
y compris celle qui vient de la non-élaboration du corps de mcc.Msg.with_LogFiles,
ce qui arrive quand mcc.Directory_Operations.Determine_App_Root_Dir en a besoin.
package mcc.Directory_Operations is
function App_Root_Dir return String;
end Mcc.Directory_Operations;
package mcc.Msg is
procedure Error (Msg : String);
end mcc.Msg;
private package mcc.Msg.with_LogFiles is
procedure Error (Msg : String);
end mcc.Msg.with_LogFiles;
with mcc.Msg;
pragma Elaborate (mcc.Msg);
package body mcc.Directory_Operations is
function Determine_App_Root_Dir return String is
begin
-- a lot of things ...
if problem then
mcc.Msg.Error ("Error message");
return "";
end if;
return path;
end Determine_App_Root_Dir;
Store_App_Root_Dir : constant String := Determine_App_Root_Dir;
function App_Root_Dir return String is (Store_App_Root_Dir);
end mcc.Directory_Operations;
with mcc.Msg.with_LogFiles;
package body mcc.Msg is
procedure Error (Msg : String) is
begin
if mcc.Globals.Interactive then
mcc.Common_Dialogs.Ok_Box (Msg);
else
Put_Line (Msg);
end if;
begin
mcc.Msg.with_LogFiles.Error (Msg);
exception
when others =>
null;
end;
end Error;
end mcc.Msg;
with mcc.Directory_Operations;
pragma Elaborate (mcc.Directory_Operations);
package body mcc.Msg.with_LogFiles is
ErrorsLogFile_Name : constant String :=
Compose(Mcc.Directory_Operations.App_Root_Dir, "rapid_errors.log");
procedure Error (Msg : String) is
begin
Create_Append (LogFile, ErrorsLogFile_Name);
Put_Line (LogFile, Msg);
Close (LogFile);
end Error;
begin
-- Initialization : Move ErrorsLogFile_Name when needed.
end mcc.Msg.with_LogFiles;
--
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/
_______________________________________________
Ada-france mailing list
[email protected]
https://mail.ada-france.org/cgi-bin/mailman/listinfo/ada-france