[Java] "Ontwerp" IRC Client/Bot

Pagina: 1
Acties:

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-08 17:59

Gerco

Professional Newbie

Topicstarter
Ik zat me te vervelen en ik dacht: "Laat ik eens een IRC bot maken in Java". Nu weet ik dat er daar vast al 1000'en van zijn, maar daar gaat het niet om.

Ik loop tegen het twee problemen aan:

Eerste probleem
Mijn IRCConnection class is een subclass van TCPConnection die de sockets enzo beheert, als er nu een regel data binnenkomt moet ik de Client (Bot) vertellen dat er een message is binnengekomen. In VB (COM eigenlijk) zou ik dit doen met een Event, die bestaan niet in Java (althans, niet zoals in VB voor zover ik weet).

Nu had ik bedacht om de Client dan een Interface te laten implementeren (IRCClient) en dan de IRCConnection een reference te geven naar die IRCClient en daar dan mooie methods op aan te roepen. Klinkt mooi, maar zijn er nog andere (lees: betere) manieren om hetzelfde te doen?

Tweede probleem
Ik dacht: laat ik eens lekker object georienteerd gaan doen en de IRC commands als classes implementeren, dan krijg je zoiets:
code:
1
2
3
sendCommand(new NICKCommand(nickname));
sendCommand(new USERCommand(nickname,realname));
sendCommand(new PRIVMSGCommand(target,text));

Ik vind dat dat er best wel leuk uitzien, alleen is het niet veel handiger om gewoon zo te doen:
code:
1
2
3
sendString("NICK " + nickname);
sendString("USER " + nickname + " blah blah :" + realname);
sendString("PRIVMSG " + target + " :" + text)

Ik vind dit er wat minder mooi uitzien, maar is de "objectgeorienteerde" aanpak in dit geval niet behoorlijk overkill?

edit:

Die ***Command classes zijn natuurlijk allemaal een subclass van IRCCommand en ze doen niets meer dan de argumenten in een string zetten en die bij .toString() weer uitspugen zodat de TCPConnection de commands als text kan verzenden. Ze verzenden zelf dus helemaal niets.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Punt1 ben ik niet zo'n ster in.
Is dat niet iets wat je met de observable/observer classes/interfaces kan oplossen?

Maar punt2, ik denk dat het wel netter is die command-classes te gebruiken, vooral als je odd moeilijkere commands wilt toepassen, dan is het niet zo flexibel om die commands helemaal tekstueel uit te schrijven.

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

Alarmnummer

-= Tja =-

Gerco schreef op 21 augustus 2002 @ 16:24:
Eerste probleem
Mijn IRCConnection class is een subclass van TCPConnection die de sockets enzo beheert, als er nu een regel data binnenkomt moet ik de Client (Bot) vertellen dat er een message is binnengekomen.
overerven is een overgewardeerd iets. Je kan een wrapper class maken die die functionaliteit aankan. (Daardoor heb je 100% controle over de beschikbare methodes).
In VB (COM eigenlijk) zou ik dit doen met een Event, die bestaan niet in Java (althans, niet zoals in VB voor zover ik weet).
Java heeft zeker wel events :)
Nu had ik bedacht om de Client dan een Interface te laten implementeren (IRCClient) en dan de IRCConnection een reference te geven naar die IRCClient en daar dan mooie methods op aan te roepen. Klinkt mooi, maar zijn er nog andere (lees: betere) manieren om hetzelfde te doen?
Mbv callbacks is inderdaad een oplossing, maar je zuo het dus ook kunnen doen via events.
Ik vind dit er wat minder mooi uitzien, maar is de "objectgeorienteerde" aanpak in dit geval niet behoorlijk overkill?
Het voordeel aan classes is dat je dus zelf nooit echte commando`s hoeft aan te roepen (en fouten kan maken). Ik zou zelf echt gaan voor commando classes.

Verwijderd

Het gaat om de duidelijkheid en de onderhoudbaarheid, niet om de neurotisiteit waarmee je OO implementeerd. Neurotisiteit is ook een veel te moeilijk woord om uit te spreken.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-08 17:59

Gerco

Professional Newbie

Topicstarter
Alarmnummer schreef op 21 augustus 2002 @ 16:36:
overerven is een overgewardeerd iets. Je kan een wrapper class maken die die functionaliteit aankan. (Daardoor heb je 100% controle over de beschikbare methodes).
In dit geval leek het me wel logisch, een IRC connectie is tenslotte een soort TCP connectie, alleen de data die eroverheen gaat heeft een bepaalde structuur. Ik kan natuurlijk ook een IRC connectie maken die een TCP connectie gebruikt, het verschil is minimaal, maar ik vraag me af waarom ik voor het ene of het andere zou moeten kiezen. Enlighten me please..
Java heeft zeker wel events :)
OK, I'm interested, hoe? wat? waar? waarom?

Er is me 1 in ieder geval ding duidelijk geworden: Commando classes zijn goed (hey, toch IETS goed gedaan). Even voor de zekerheid: Die classes zijn dus eigenlijk een soort structs ofzo, ze doen extreem weinig. Een voorbeeld:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class PRIVMSGCommand extends IRCCommand {
    private String _target = null;
    private String _text   = null;

    public PRIVMSGCommand(String target, String text) {
        _target = target;
        _text = text;
    }

    public String toString() {
        return "PRIVMSG " + _target + " :" + _text;
    }
}

Is dit ook zo'n beetje wat jullie voor ogen hadden toch ik het uitlegde? Of heb ik toch iets verkeerd begrepen?

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


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

Alarmnummer

-= Tja =-

Je hebt alles goed begrepen

event code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//event
class PindaEvent extends  EventObject{
}

//listener
interface PindaListener extends EventListener{
    public void pindaKlaar(PindaEvent e);
}


//dit plaats je in je pindabak class..
List listenerList = new LinkedList();

firePindaKlaar(){
     PindaEvent e = new PindaEvent();
     for(Iterator itt = listenerList.iterator();itt.hasNext();){
          ((PindaListener)itt.next()).pindaKlaar(e);
     }
}

void addPindaListener(PindaListener l){
    listenerList.add(l);
}


Ik hoop dat je in ieder geval hiermee uit de voeten kan.

Verwijderd

Gerco schreef op 21 augustus 2002 @ 17:03:
OK, I'm interested, hoe? wat? waar? waarom?
Op zich is het niet verboden een gegeven link eens te bekijken, de IBM tutorial legt het een en ander duidelijk uit.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-08 17:59

Gerco

Professional Newbie

Topicstarter
Zef, ik heb op mn werk een proxy en een systeembeheerder die van sites blokkeren houd. Het is al een godswonder dat ik hier op GoT kan komen... sourceforge is bijvoorbeeld al taboe (ik weet niet of het er iets mee te maken heeft dat hij MS freak is, maar ik vind het wel opvallen)

Ik zal je link zeker bekijken aangezien ik nu weer thuis ben.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Fijn, zo'n systeembeheerder :o

Verwijderd

Gerco schreef op 21 augustus 2002 @ 17:03:
[...]

In dit geval leek het me wel logisch, een IRC connectie is tenslotte een soort TCP connectie, alleen de data die eroverheen gaat heeft een bepaalde structuur. Ik kan natuurlijk ook een IRC connectie maken die een TCP connectie gebruikt, het verschil is minimaal, maar ik vraag me af waarom ik voor het ene of het andere zou moeten kiezen. Enlighten me please..
Om de gebruiker van een IRCconnection class tegen zichzelf te beschermen, zou ik kiezen voor private aggregation en hem daarmee (in tegenstelling tot public inheritance) niet de mogelijkheid geven zelf aan de connection of verstuurde/ontvangen bytes te gaan klooien. Het doel van je IRCconnection class is juist om die low-level zaken te abstraheren, dus lijkt het me gepast om de TCPconnection voor de gebruiker verborgen houden.

In hoeverre het verschil minimaal is hangt af van op wat voor inheritance of aggregation je doelt (public/protected/private).

Verwijderd

Gerco schreef op 21 augustus 2002 @ 17:03:
[...]
In dit geval leek het me wel logisch, een IRC connectie is tenslotte een soort TCP connectie, alleen de data die eroverheen gaat heeft een bepaalde structuur. Ik kan natuurlijk ook een IRC connectie maken die een TCP connectie gebruikt, het verschil is minimaal, maar ik vraag me af waarom ik voor het ene of het andere zou moeten kiezen. Enlighten me please..
[...]
In theorie kan IRC ook over iets anders dan TCP gedaan worden. Dat is in jouw geval niet zo waarschijnlijk, maar ik zeg het maar even.

Ik zou er overigens ook even over nadenken of je bot (misschien in de toekomst) connecties met verschillende IRC servers zou moeten aankunnen of dat je daarvoor losse instanties op wil starten.

Daarnaast kan het zijn dat je de bot bij 1 server meerdere kanalen wil kunnen laten joinen. In beide gevallen heb je al gauw nog wat extra classes/abstracties nodig.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 30-08 17:59

Gerco

Professional Newbie

Topicstarter
Verwijderd schreef op 21 augustus 2002 @ 18:30:
In hoeverre het verschil minimaal is hangt af van op wat voor inheritance of aggregation je doelt (public/protected/private).
Ik doel op private aggregation, voor zover ik weet bestaat er geen private inheritance in Java, maar ik heb me al eens eerder vergist in dingen die Java volgens mij niet had.

Met "het verschil is minimaal" bedoel ik dat de IRCConnection class niet veel veranderd hoeft te worden, alleen ipv aanroepen op zn superclass zet je dr even een _connection voor ofzo. En je moet je TCPConnection openen en closen.
Ik zou er overigens ook even over nadenken of je bot (misschien in de toekomst) connecties met verschillende IRC servers zou moeten aankunnen of dat je daarvoor losse instanties op wil starten.
Multiple servers waren wel de bedoeling, maar daar voorziet het ontwerp al in als ik het goed heb. Ik heb een IRCClient die met events de berichten van IRCConnection krijgt. Dan kan de IRCClient bepalen van welke IRCConnection (en dus server) de event kwam en de gewenste actie ondernemen.

Voor meerdere channels heb ik nog even niets bedacht, maar meerdere channels joinen is erg eenvoudig (ik weet niet of je bekend bent met het IRC protocol), alles gaat over 1 connectie en je krijgt bij alles te horen over welke channel het gaat. Ik wil uiteindelijk wel een IRCChannel klasse maken waarover alle communicatie voor 1 Channel gaat lopen. Dan moet ik alleen even nadenken over wat ik met private messages ga doen.

[ Voor 0% gewijzigd door Gerco op 22-08-2002 08:10 . Reden: typo ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Gerco schreef op 22 augustus 2002 @ 08:09:
[...]

Ik doel op private aggregation, voor zover ik weet bestaat er geen private inheritance in Java, maar ik heb me al eens eerder vergist in dingen die Java volgens mij niet had.
Nope, er is geen private aggregation iig niet dat ik weet
Met "het verschil is minimaal" bedoel ik dat de IRCConnection class niet veel veranderd hoeft te worden, alleen ipv aanroepen op zn superclass zet je dr even een _connection voor ofzo. En je moet je TCPConnection openen en closen.
Wat sneechy waarschijnlijk bedoelt is dat je beter een wrapper class om TCPConnection heen kan bouwen. Hiermee stel je je eigen (STRAKKE!) interface samen voor de IRCConnection en geef je de gebruiker (van een IRCConnection object ) geen mogelijkheid om te vervallen in het raw uitlezen van bytes en daarmee je gestelde interface ( en checks dus ook ) te omzeilen.
Multiple servers waren wel de bedoeling, maar daar voorziet het ontwerp al in als ik het goed heb. Ik heb een IRCClient die met events de berichten van IRCConnection krijgt. Dan kan de IRCClient bepalen van welke IRCConnection (en dus server) de event kwam en de gewenste actie ondernemen.
Zou moeten werken toch :)
Voor meerdere channels heb ik nog even niets bedacht, maar meerdere channels joinen is erg eenvoudig (ik weet niet of je bekend bent met het IRC protocol), alles gaat over 1 connectie en je krijgt bij alles te horen over welke channel het gaat. Ik wil uiteindelijk wel een IRCChannel klasse maken waarover alle communicatie voor 1 Channel gaat lopen. Dan moet ik alleen even nadenken over wat ik met private messages ga doen.
Je zou dan kunnen denken aan dat IRCConnection een IRCChannel object kan teruggeven

code:
1
2
3
4
IRCChannel dpc = connection.getChannel( "dpc" );
dpc.speak( "Blaaat. 6,8 Mkeys/s " );
dpc.setTitle( "Nu zet ik de title op 6,8 Mkeys/s" );
dpc.disconnect( );


Ik denk dat je er wel rekening mee moet houden nu in je early design, omdat ik persoonlijk dan een hele laag bovenop je IRC connectie zou gaan leggen.

Bijv niet een Private message versturen via IRCConnection maar zo:

code:
1
2
IRCPrivateMessageStream glimi= connection.getPrivateMessageStream( "nick van de usert" );
glimi.send( "Ey dude!" );


En dan ook zo met channels en met de servercommands :)
Misschien heb je er wat aan, zuig het even uit de losse duim maar ben nog een beetje moe, dus let even niet op de naamgeving

Verwijderd

Glimi schreef op 22 augustus 2002 @ 09:42:
Wat sneechy waarschijnlijk bedoelt is dat je beter een wrapper class om TCPConnection heen kan bouwen. Hiermee stel je je eigen (STRAKKE!) interface samen voor de IRCConnection en geef je de gebruiker (van een IRCConnection object ) geen mogelijkheid om te vervallen in het raw uitlezen van bytes en daarmee je gestelde interface ( en checks dus ook ) te omzeilen.
Dat was eerlijkgezegd niet wat ik bedoelde; ik stelde alleen voor om het TCPconnection object een private member te maken in plaats van een public base class. Als je verder alsnog methods van de TCPconnection beschikbaar wil maken voor gebruikers van de IRCconnection (ik zou overigens niet weten welke) kun je die eventueel door IRCconnection laten deligeren.

  • Glimi
  • Registratie: Augustus 2000
  • Niet online

Glimi

Designer Drugs

(overleden)
Je bouwt dus om de TCP connection heen ipv het te overerven voor de methodes. Dan kom je naar mijn inzicht toch op een soort of wrapperclass

Verwijderd

Glimi schreef op 22 augustus 2002 @ 19:43:
Je bouwt dus om de TCP connection heen ipv het te overerven voor de methodes. Dan kom je naar mijn inzicht toch op een soort of wrapperclass
Ah, nu pas begrijp ik dat je met die 'wrapper class' de IRCconnection zelf bedoelt. De term wrapper class lijkt me eigenlijk niet zo op z'n plaats omdat het hier gaat om een niet light-weight class die zelf duidelijk allerlei nieuwe ongerelateerde functionaliteit toevoegt.
Pagina: 1