IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Application modulaire et chargement de configuration


Sujet :

Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut Application modulaire et chargement de configuration
    Bonjour à tous,

    Dans le cadre d'un développement d'application modulaire, je souhaiterais trouver le "meilleur" moyen de charger des paramètres définis par le développeur du module. Je m'explique

    Supposons un core sur lequel je branche un ensemble de modules. Chacun de ces modules possède (forcément) un ensemble de méthodes dont la signature est invariante (type plug() et unplug() par exemple). Maintenant, il arrive que certains de ces modules définissent un ensemble d'attributs qui, dans l'idéal, pourraient être initialisés via une configuration définie par l'utilisateur.

    Malheureusement, je ne peux pas me permettre de demander à l'utilisateur de trifouiller un fichier de configuration (les Properties de l'API JavaSE dans le meilleur des cas), et pour cause : l'un de mes modules contiens des attributs qui sont des objets bien spécifiques (par exemple, une classe DataFile qui prend en constructeur un chemin vers un fichier ou un File, et un objet Class<T> (donc DataFile(path, X.class)). Alors bien sûr, je pourrais définir des options dans un fichier Properties du type

    dataPath="le chemin"
    parserClass="nom de la classe"

    et faire appel à un Class.forName(), mais je ne trouve pas cette façon de faire "élégante".

    Au lieu de procéder de la sorte, j'ai préféré définir une annotation @Configurable(ignore = {attributs à ignorer pour la configuration}, optional = {attributs optionnels}) à placer au niveau de la définition de la classe (du module), permettant de le définir comme étant Configurable (no way ?!).

    Ensuite, lors du chargement de mon core, et plus précisément lors de la découverte des modules installés (sous format .jar), je vérifie si le module possède cette annotation.
    Si tel est le cas, j'appelle une méthode configure() sur mon module prenant en paramètre une Map<String, Object>, dont chaque clé correspond en fait au nom d'un attribut de mon module. Par exemple, supposons que j'insère dans cette map un couple de type ("file1", new DataFile("./test.txt", SomeClass.class)). Vous l'aurez donc deviné, je procède à l'initialisation de ces objets par introspection : à chaque clé de la map correspondant au nom de l'attribut de mon module, j'attribue à ce dernier la valeur associée à la clé dans ma map (j'utilise le type Object histoire d'être sûr qu'au moins je pourrais mettre n'importe quoi).

    Cette façon de procéder marche très bien mais possède un seul inconvénient qui, j'avoue, me chagrine un peu : il faut construire une telle map à fournir au module, ce qui peut être un peu pénible et rébarbatif, de plus que celle-ci demande forcément à être codée, alors que le paradigme du fichier de configuration relève plus de ce qui se fait aujourd'hui (mais offre moins de souplesse quant à la définition des paramètres à utiliser, car ne marche qu'avec des types String (ou du moins des flux de caractères)).

    Je ne souhaite pas serialiser mes objets à utiliser non plus, car ceux-ci ne sont pas statiques, et leur valeur peut changer d'une exécution à l'autre de mon application.

    Si jamais vous voyez ici un soucis de conception, ou une meilleure - voire la meilleure - façon de procéder, je suis grandement preneur de vos conseils avisés.

    Bonne soirée à vous !

    et merci d'avoir pris le temps de lire mon pavé

  2. #2
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    difficile de faire une réponse courte : le niveau des utilisateurs qui configurent est un critère essentiel.
    J'ai un besoin analogue sur un gros projet et voici ce que j'ai fait:
    - j'ai un fichier de description/configuration qui a une syntaxe de DSL (domain specific language) basée sur les Builders de Groovy . J'ai des utilisateurs relativement avertis mais ça a coincé au début (ils voulaient bien du XML mais pas un truc qu'ils ne connaissaient pas). Finalement à l'usage ils ont trouvé ça extrèmement souple et pratique donc c'est passé.
    - à partir de cette base j'ai des options de paramétrages supplémentaires:
    ** je génère un squelette de fichier .properties dans lequel l'utilisateur peut changer certains paramètres (utilisés par des objets complexes)
    ** j'ai aussi une base de données de configuration et une API qui permet de réaliser des outils interactifs pour manipuler ces paramètres et les enregistrer
    Bref c'est un ensemble d'outils pas franchement simple à implanter mais très pratique à l'usage (on peut décrire de diverses manières la création d'objets, on peut décrire les paramètres, les contraintes associées si on veut le changer, et on les documente).
    (certains vont penser à Spring ... mais justement j'ai écrit cet outil pour remplacer Spring)

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut
    Quand tu me dis que tu as utilisé une syntaxe DSL, dois-je comprendre que tu as toi même définit une syntaxe particulière (en te basant sur ce que tu m'as dit, à savoir les Builders de Groovy) ? Car je ne me suis jamais penché sur les langages dédiés...

  4. #4
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par huzard Voir le message
    Quand tu me dis que tu as utilisé une syntaxe DSL, dois-je comprendre que tu as toi même définit une syntaxe particulière (en te basant sur ce que tu m'as dit, à savoir les Builders de Groovy) ? Car je ne me suis jamais penché sur les langages dédiés...
    yes
    mais ça reste du Builder pur sucre...
    exemple tres simple 1: (textes rédigés par des programmeurs formés)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    String limitLo = "limitLo"
    String limitHi = "limitHi"
     
    CCSBuilder builder = ["ccs-refrig"]
     
    builder.
        main (RefrigTest, argMap("main", 10000, "hdw")) {
            Daq1       (MCCDevice, argMap("TC_AI", "00087534"))
           // ici il n'y a que deux paramètres modifiables limitLo et LimitHo
            CmpDisTmp  (MonChannel,
                        argMap("Compressor discharge temperature", "C",
                               "flag", aDbl(limitLo, 0.0), 0.0,
                               "mtrip", aDbl(limitHi, 0.0), 0.0,
                               "Daq1", 0, "TEMP", "TC:T", 0, 0.0, 1.0))
     // etc.. etc...
    extrait d'un très gros descripteur beaucoup plus compliqué (avec des boucles de programmation, des variables, ...);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
                    {//begin description of bridge's children          
     
                            // tcp Proxy
                            tcpProxy (CanOpenProxy,
                                    argMap(aString("name", "tcpProxy"),
                                        anInt("tickMillis", 1000),
                                        anInt("portNumber", 50000,[static:true, constraints:1024..99000]),
                                        aString("myClientName","TestBench",[static:true]),
                                        anInt("expectedNodesNB", 6),                                   
                                        anInt("hardwareBootTimeout",2000, [description:"A timeout for the harwdare booting process",constraints:1000..10000])))
     
                            // can open devices
                            ai814 (CanOpenADC, 
                                    argMap(aString("name", "ai814"),
                                        anInt("tickMillis", 3000),
                                        aString("nodeID","21"),
                                        aString("serialNB","c7c40234"),
                                        aString("transmissionType","1")))
    ça va générer automatiquement un fichier .properties (extrait)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    #********  tcpProxy//expectedNodesNB
    #** 
    #** type : integer (example : 6)
    #**
    #********
     
    #tcpProxy//expectedNodesNB = 6
     
     
    #********  tcpProxy//hardwareBootTimeout
    #** A timeout for the harwdare booting process
    #** constraints : 1000..10000 ; type : integer (example : 6)
    #**
    #********
     
    #tcpProxy//hardwareBootTimeout = 2000
     
     
    #********  tcpProxy//myClientName
    #** 
    #**  static parameter (not modifiable at runtime)
    #** type : String
    #**
    #********
     
    #tcpProxy//myClientName = TestBench
     
     
    #********  tcpProxy//portNumber
    #** 
    #**  static parameter (not modifiable at runtime)
    #** constraints : 1024..99000 ; type : integer (example : 6)
    #**
    #********
     
    #tcpProxy//portNumber = 50000
    l'utilisateur (moins expert) peut alors decommenter une ligne et changer un paramètre.
    par ailleurs les paramètres sont enregistrés automatiquement dans une base de donnée et on peut avoir des opérations de modifications de paramètres au runtime (sauf les paramètres marqués "static") et ensuite enregistrer dans la base (et dans un fichier.properties) le résultat des modifications opérées au runtime.
    autres aspects:
    - il y a differentes possibilités de génération des objets (y compris de l'injection de références entre les objets)
    - on peut faire des descriptions avec des options (par exemple dans notre projet on peut opter pour des exécutions avec du vrai hardware ou avec une simulation)
    - ces descriptions sont "compilables" (on peut les compiler pour les tester et ensuite charger plus tard le résultat binaire)
    - elles permettent de générer des canevas de tests (le générateur analyse les types de paramètres et propose des batteries de tests)

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2013
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2013
    Messages : 14
    Par défaut
    Hmm... ça m'a l'air assez compliqué quand même. Du moins, trop compliqué, dans l'absolu, pour ce que je veux faire. Non pas que j'ose dire que ta méthode me semble mauvaise, mais plutôt le contraire : c'est trop pointu pour mon cas. Cela dit, je vais garder ça de côté car ça m'a l'air très intéressant à étudier. En tout cas, je te remercie pour le temps que tu as pris pour me répondre

    Bonne fin de journée

Discussions similaires

  1. Temps de chargements, application modulaire
    Par arnaud.tlse dans le forum Flex
    Réponses: 4
    Dernier message: 29/01/2010, 11h47
  2. Problème de refresh dans une application modulaire
    Par TigrouMeow dans le forum Windows Forms
    Réponses: 8
    Dernier message: 11/10/2007, 15h06
  3. Réponses: 7
    Dernier message: 16/06/2007, 12h03
  4. Build / application modulaire
    Par Oscar Hiboux dans le forum Maven
    Réponses: 1
    Dernier message: 05/12/2006, 17h38
  5. Comment faire une application modulaire
    Par JuJu° dans le forum C++Builder
    Réponses: 3
    Dernier message: 04/08/2006, 11h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo