[Java] reflection in UML weergeven

Pagina: 1
Acties:

  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
hallo,

voor een schoolproject zijn wij bezig een app te maken. Hiervoor hebben we een mooi class diagram gemaakt. Wat de bedoeling is, is dat het systeem uit modules bestaat.
Welke module er nodig is is van tevoren (at-compile time) niet bekend, dat weet je pas at-runtime.
Nu denk ik dat we dit met reflection zullen moeten doen. Probleem is alleen dat we dit ook in UML willen weergeven (met Together) Alleen hoe it nu weer moet, geeeeen id.
Ik heb in het GoF boek gekeken naar een imlementatie hiervan, alleen komt dat niet echt overeen met de manier zoals wij het hebben (of denken goed te hebben ;-) )

Afbeeldingslocatie: http://java.cirqular.nl/voorbeeld.gif
Zoiets hebben we (even simpeler en kleiner weergegeven)

De bedoeling is dat de Core, via reflection, een instantie van de desbetreffende module aanmaakt. Deze krijgt dan een instantie van Log by-reference mee.
Alleen hoe geef je dit in UML weer, voorop gesteld dat deze manier klopt. Wij zaten aan een AbstractFactory te denken, alleen hebben ze hier nog een interface meer (voor de moduleManager) :?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Je moet niet gaan werken met reflection (denk na: wat zou je in godsnaam moeten aanroepen?). Je moet gewoon een interface opstellen waaraan een module moet voldoen.

Java:
1
2
3
4
5
interface Module{
     void start();
     void stop();
      String getDescription();
}


En dan kan je hier een implementatie van maken (jouw AModule en BModule) en je hoofd applicatie moet gewoon met een Module kunnen omgaan, en dan kan hij automatisch ook met iedere implementatie ervan omgaan.

Leuk trouwens om te zien dat jullie met design patterns bezig zijn, maar wat ik hier boven zeg is de basis van object oriented programming: layer of indirection.

[ Voor 28% gewijzigd door Alarmnummer op 27-10-2004 18:11 ]


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Misschien was mijn plaatje (en uitleg) niet helemaal duidelijk.
De applicatie is het startpunt. Deze doet een aantal dingen:
- instantie van Log maken
- instantie van een GUI maken
- instatantie van een db pool maken

De gebruiker bepaald vanuit de applicatie, dmv een knopje bijvoorbeeld, welke module e benodigd is. De Core maakt op een-of-andere-manier een instatantie van de module en roept daar of een default methode van aan of een bepaalde, opgegeven, methode.

Misschien zo al iets duidelijke :)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

TheRebell schreef op 27 oktober 2004 @ 18:20:
Misschien was mijn plaatje (en uitleg) niet helemaal duidelijk.
De applicatie is het startpunt. Deze doet een aantal dingen:
- instantie van Log maken
- instantie van een GUI maken
- instatantie van een db pool maken

De gebruiker bepaald vanuit de applicatie, dmv een knopje bijvoorbeeld, welke module e benodigd is. De Core maakt op een-of-andere-manier een instatantie van de module en roept daar of een default methode van aan of een bepaalde, opgegeven, methode.

Misschien zo al iets duidelijke :)
Ja.. maar dat doet absoluut geen afbraak aan mijn verhaal.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LogModule implements Module{
     void init(Environment env){
           ..sluit de loggers aan en doe ander leuks
     }
}

class GuiModule implements Module{
     void init(Environment env){
          ModulePanel panel = env.getModulePanel();
          panel.addModule(buildMooieGui());
     }

      ....buildMooieGui(){}
}


aanmaken module:

code:
1
2
3
4
5
6
7
8
9
public Module startModule(String modClassStr){
   Class modClass =Class.forName(moduleClassStr);
   Module module = (Module) modClass.newInstance();
   module.init(refNaarEnvironment);
   return module;
}

startModule("com.bla.GuiModule");
startModule("com.bla.LogModule").

[ Voor 38% gewijzigd door Alarmnummer op 27-10-2004 18:35 ]


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Alarmnummer schreef op 27 oktober 2004 @ 18:25:
aanmaken module:

code:
1
2
3
4
5
6
7
8
9
public Module startModule(String modClassStr){
   Class modClass =Class.forName(moduleClassStr);
   Module module = (Module) modClass.newInstance();
   module.init(refNaarEnvironment);
   return module;
}

startModule("com.bla.GuiModule");
startModule("com.bla.LogModule").
:? is dit geen reflection dan....

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

TheRebell schreef op 27 oktober 2004 @ 19:40:
[...]


:? is dit geen reflection dan....
Alleen die module aanmaken... Maar alle aanroepen erop zijn dus gewoon normaal. Dit is dus iets volledigs anders dan wat jij wilt gaan doen: namelijk alle calls mbv reflection doen. Ik heb de compiletime garantie dat na die newInstance mijn objecten van het goeie type zijn.. jij niet.

  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Alarmnummer schreef op 27 oktober 2004 @ 19:46:
Alleen die module aanmaken... Maar alle aanroepen erop zijn dus gewoon normaal. Dit is dus iets volledigs anders dan wat jij wilt gaan doen: namelijk alle calls mbv reflection doen. Ik heb de compiletime garantie dat na die newInstance mijn objecten van het goeie type zijn.. jij niet.
Java:
1
2
3
class AModule extends Module{
    // enz...
}

zo kan het toch ook.

Alleen wat je dan krijgt, en jij waarschijnlijk bedoeld, is dat je dmv
Java:
1
2
3
4
Method actionMethod;

actionMethod = module.getMethode(aMethod);
actionMethod.invoke(moduleInstance);

(zoiets ;) )
gaat doen.

Alleen hoe ga je dan een bepaalde method van een module aanroepen nadat je hier een instantie van hebt gemaakt? Want die is ook telkens anders...

[edit]

als je een instantie hebt van een module (bv AModule) en je wilt dan daarvan een method aanroepen, dan gaat ModuleManager dat dus doen. Dat zou via init() kunnen:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Module Log implements Module
{
        void init(Environment env) {
               String method = env.getMethodName();
               this.method(); // dit werkt natuurlijk niet

                // misschien zo?
                Method actionMethod;
                actionMethod = this.getMethod(env.getMethodName());
                actionMethod.invoke(this);  // ?!
        }

        public void someMethod() {
                // doe iets
         }
}


binnen een module kun je verschillende methods hebben. Die hebben niet alle modules, behalve een aantal vaste methods zoals init()
Alleen dan begint het wel weer veel op Reflection te lijken :?

[ Voor 44% gewijzigd door TheRebell op 27-10-2004 20:48 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

TheRebell schreef op 27 oktober 2004 @ 20:22:
[...]


Java:
1
2
3
class AModule extends Module{
    // enz...
}

zo kan het toch ook.
Zo kan het ook.. maar persoonlijk gebruik ik interfaces om types te definieren (en dat doe je hier). Maar op dit moment is het lood om oud ijzer.
Alleen hoe ga je dan een bepaalde method van een module aanroepen nadat je hier een instantie van hebt gemaakt? Want die is ook telkens anders...
Dat moet je dus ook niet doen. Geef die module een performeAction methode ofzo. Dan kan polymorifsme mooi oplossen welke methode daadwerkelijk aangeroepen moet worden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Module{
     abstract void actionPerformed();
}


class LogModule extends Module{
     void actionPerformed(){
         logger.log("ohh.. ik moet schijnbaar iets loggen');
     }
}

class OntplofModule extends Module{
     void actionPerformed(){
         wereld.ontplof();
     }
}



Nu kun jij in de applicatie gewoon zeggen:
module.actionPerformed().

En dan maakt het niet meer uit of het een LogModule is, of een OntplofModule. (dit heet polymorfisme.. check je boeken)
binnen een module kun je verschillende methods hebben.
Yep... maar denk nu even goed na.. Stel jij maakt een module: de IkHebHongerModule.. die heeft een methode.. geefMijEten.. hoe moet die applicatie dan weten dat hij die methode moet aanroepen? en niet ikWilDrinken? of een hele andere??? Jij hebt een bepaald contract nodig waarin jij de communicatie van de applicatie naar de module beschrijft (en eventueel andersom: callback).

Jij moet niet met reflection gaan pielen omdat dat een volslagen kut oplossing is.

[ Voor 12% gewijzigd door Alarmnummer op 27-10-2004 20:58 ]


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Alarmnummer schreef op 27 oktober 2004 @ 20:56:
Yep... maar denk nu even goed na.. Stel jij maakt een module: de IkHebHongerModule.. die heeft een methode.. geefMijEten.. hoe moet die applicatie dan weten dat hij die methode moet aanroepen? en niet ikWilDrinken? of een hele andere??? Jij hebt een bepaald contract nodig waarin jij de communicatie van de applicatie naar de module beschrijft (en eventueel andersom: callback).

Jij moet niet met reflection gaan pielen omdat dat een volslagen kut oplossing is.
ik heb het gevoel dat we een beetje langs elkaar heen lullen 8)7

Als de app wordt gestart is er niet bekend welke module/actie er moeten worden uitgevoerd. Hiervoor moet er dus een default class zijn. Hiervan wordt dan een instantie gemaakt en de default actie van uitgevoerd (bv via de init voor een mooi welkom schermpje ofzo ;) )
Als een gebruiker nu op een knopje drukt voor een bepaalde module (bv AModule) dan zal een event ervoor moeten zorgen dat de core (de 'hoofd' class) weet dat er iets geladen moet worden.
De core weet dus nu welke module er gevraagd wordt. Hiervan maakt deze een instantie en voert de actie uit, voor zover deze bekend is. Is deze er niet dan heb je bv de init methode.
Stel nu dat er binnen een module een actie wordt uitgevoerd, bv het opslaan van iets. Dan is het nodig om te weten welke module dat gaat doen en welke actie hiervoor noodzakelijk is (opslaan dus)
De core kan nu de module achterhalen, instantieren en zal via een action bepalen welke methode dat wordt. Voor het opslaan van iets bij de AModule kun je dus hebben dat je de methode 'opslaan' wilt uitvoeren van de class AModule.

Elke module heeft dus een aantal standaard methode waarvan we zeker weten dat ze er zijn (bv de init). Verder heeft een module een aantal andere methods, voor het opslaan, zoeken, updaten, whatever allemaal.

Het bepalen en instantieren van een module at runtime is duidelijk volgens jou manier alarnmummer. Alleen hoe wil je dan die aanroepen. Je kunt niet direct de naam van de method achter 'this' plakken ;)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

TheRebell schreef op 27 oktober 2004 @ 22:11:
[...]


Elke module heeft dus een aantal standaard methode waarvan we zeker weten dat ze er zijn (bv de init). Verder heeft een module een aantal andere methods, voor het opslaan, zoeken, updaten, whatever allemaal.
Kijk nu eens naar mijn actionPerformed.

  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Kijk nu eens naar mijn actionPerformed.
* TheRebell zet bril op B)
Alarmnummer schreef op 27 oktober 2004 @ 20:56:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Module{
     abstract void actionPerformed();
}


class LogModule extends Module{
     void actionPerformed(){
         logger.log("ohh.. ik moet schijnbaar iets loggen');
     }
}

class OntplofModule extends Module{
     void actionPerformed(){
         wereld.ontplof();
     }
}
show me the light :? Ik snap er geen drol van.
Hoe kun je nu onderscheid maken tussen verschillende methods van een class?!

Java:
1
2
3
4
5
6
7
8
9
10
11
12
abstract class Module{
     abstract void actionPerformed();
}

class OntplofModule extends Module{
     void actionPerformed(){
         wereld.ontplof();
     }

      private void ontplof() {}
      private void ontplofNiet() {}
}

als je nu module.actionPerformed() anroept (dus op de class OntplofModule) dan voert ie de method ontplof() uit (hoe kom je btw bij wereld.ontplof() ?? explain)
Wat als ik nu ontplofNiet() wil aanroepen.... Dat zul je toch op een andere manier moeten doen

Verwijderd

TheRebell schreef op 27 oktober 2004 @ 23:01:
als je nu module.actionPerformed() anroept (dus op de class OntplofModule) dan voert ie de method ontplof() uit (hoe kom je btw bij wereld.ontplof() ?? explain)
Wat als ik nu ontplofNiet() wil aanroepen.... Dat zul je toch op een andere manier moeten doen
Het bestaan van reflection zet je duidelijk op het verkeerde been. Je moet even een gedacten twist maken. Het concept is erg simpel, maar je ziet dus inderdaad het licht niet ;)

Bij een plug-in based design moet je helemaal niet willen komen bij onbekende methods. Er is -1- interface, en alle plug-ins (classes die je dynamisch inlaad en @ compile time onbekend zijn) implementeren deze interface,

Alles, maar dan ook echt alles dient via dit vaste contract te gaan. Als je echt totaal verschillende dingen wilt met verschillende plug-ins dan defineer je verschillende types plug-ins met voor elke groep een bijbehorende interface.

Jouw gedachten zijn vertroebeld door reflection ( lured into the darkside :+ ) , maar het interface/contract mechanisme is juist niet beperkend. Kijk maar eens naar hoe plug-ins in andere projecten gebruikt worden (bv Eclipse, of de psx emulators).

PS

Als waarschuwing hier een triest voorbeeld van hoe slecht het met iemand kan aflopen als je overloop naar de darkside of java:

[rml][ JAVA] Implementen van een Interface d.m.v. reflection?[/rml]

(arme Cybarite :'( )

Reflection heeft wel zijn toepassingen hoor, maar dat moet je meer zoeken in de richting van tools support en java bean achtige dingen.

[ Voor 14% gewijzigd door Verwijderd op 27-10-2004 23:27 ]


  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
poowee, goed dat er nog een paar Jedi's rondlopen ;)

Het is duidelijk dat ik teveel aan een reflection-manier blijf denken, dat speelt een beetje parten.
Oke het is duidelijk dat je voor je modules een interface hebt. Ook het instantieren van een module is duidelijk, alleen het uitvoeren van een bepaalde methode niet :?

Zou het dan kloppen als ik zeg dat als je een aantal modules hebt AModule, BModule dat deze beiden een interface hebben waarin de methods staan die deze modules hebben?
Dus bv:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface AModuleInterface {
      void init();
     void blaat();
     void toet();
}

public interface BModuleInterface{
       void init();
       void kaas();
       void wordt();
}


// of gewoon -1- interface voor beide modules
public interface Module{
       void init();
       // misschien nog iets
}

of is het wel -1- interface voor alle modules, dan heb je alleen geen beschrijving van de methods.

Nu alleen nog hoe je het dan aanroept, aangezien de core 'van bovenaf' doorkrijgt welke actie er moet worden uitgevoerd

Verwijderd

[quote]TheRebell schreef op 27 oktober 2004 @ 23:54:
poowee, goed dat er nog een paar Jedi's rondlopen ;)

;) Het geval van Cybarite is dan ook wel erg extreem. Dat is de emperor himself. (blijkt ook wel uit zijn ondertitel). (no offence Cybarite j/k)
of is het wel -1- interface voor alle modules, dan heb je alleen geen beschrijving van de methods.
Het hangt een beetje van de bedoeling van je A en B modules af. Waarschijnlijk zijn het verschillende concepten, en hebben ze dus verschillende interfaces nodig.

Om het makkelijk te maken, aanschouw een plug-in gebasseerde emulator als epsxe. Deze heeft plug-ins voor onder andere beeld renderen, geluid afspelen, en input afhandeling. Iedereen kan zijn eigen renderer voor epsxe schrijven, zonder dat de makers van de emulator deze ooit hoeven te kennen tijden hun compile (ergo, het plug-in concept).

Hoewel het beiden plug-ins voor hetzelfde systeem zijn, is een renderer iets heel anders als een input afhandeler. Heel simpel heeft een renderer mischien methodes als init() en drawImage(), terwijl de input afhandeler init() en getKey() heeft. Je defineerd dus 2 interfaces voor 2 soorten plug-ins.
Nu alleen nog hoe je het dan aanroept, aangezien de core 'van bovenaf' doorkrijgt welke actie er moet worden uitgevoerd
Als het goed is dan zijn er maar een beperkt aantal acties mogelijk, namelijk precies die acties die in je interface staan en waarvoor dus een contract bestaat.

De user van je core initieert zo'n actie, en de core roept bij elke actie een vaste methode op. De implementatie van deze methode is geheel afhankelijk van de ingeladen plug-in.

In het simpelste geval, heb je bv een interface met 2 methods. In je GUI heb je 2 buttons. Als op button 1 wordt gedrukt roep je method 1 aan en als op button 2 wordt gedrukt method 2.

Elke mogelijke actie (op welke manier die ook binnenkomt) is vast gekoppeld aan een method. Dat is je contract waar beide partijen zich aan moeten houden.

  • TheRebell
  • Registratie: Oktober 2000
  • Laatst online: 20-05 16:00
Zo ik ben weer even bezig geweest met de vele ideen...

Ik heb nu het volgende diagram
Afbeeldingslocatie: http://java.cirqular.nl/pgs_2.gif
(clickable)..zullen nog wel wat foutjes inzitten maargoed

Alleen zit ik dus even met die moduleManager, moet die ook een interface hebben of zou dat zo genoeg zijn.

Nu wordt het allemaal nog leuker, want een Module heeft als uitvoer een formulier om bv wat in te vullen. Dit zou je in een FormClass ofzo kunnen zetten met enkele methods per formuliertje. Maar op een formulier heb je ook een knopje zitten om bv een formuliertje op te slaan.... Die method moet een module dus ook hebben, die komt dan zeker ook in de interface te staan :?
Ook die actions voor buttons moeten ergens komen....
Pagina: 1