Design van een errorlogger.

Pagina: 1
Acties:
  • 269 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Hoi. :P

Ik ben bezig met het maken van een ErrorLogging class. Deze class moet kunnen
gebruikt worden in applicaties die aan errorlogging doen.
Het moet mogelijk zijn om errors naar een databank of naar een file te loggen.

Gisteren was ik begonnen met in C# een DLL te maken die één class had, nl. Logger
Deze class zag er ongeveer als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Logger
{
    #region Attributes
    private bool              m_LogToDatabase;
    private SqlConnection     m_Conn;
    private SqlCommand        m_cmdWriteMessage;
    private StreamWriter      m_LogFile;
    private string            m_LogFileName;
    #endregion

    #region Properties
    #endregion

    #region Public Methods
    public void StartLogging()
    public void WriteLog ( string ErrorMessage )
    public void EndLogging()
    #endregion
}


Deze class ging dus zelf gaan nagaan of errors naar de databank moesten gelogged worden
of naar een file. Dit heeft wel als gevolg dat er in de methods heel wat if - statements
voorkomen en dat ik in dit geval enkel naar een file of naar een Sql Server databank
kan loggen.

Gisterenavond was ik echter wat in m'n GoF - boek aan het lezen en daar stuitte ik op het
"Strategy-pattern". IMHO zou dit pattern goed toepasbaar zijn voor m'n ErrorLog class.

Ik heb net ff een schema'tje gemaakt en dat zou er dan als volgt uit zien:
Afbeeldingslocatie: http://users.pandora.be/fgzone/schema.jpg

Op deze manier kan ik later nog eenvoudig een class toevoegen die het bv. mogelijk maakt
om naar bv een Oracle databank te gaan loggen.

Aangezien dit m'n eerste aanraking is met design patterns had ik graag wat input ontvangen
van de mensen die daar al wat meer ervaring mee hebben. Ben ik op de goede weg? Zie ik
dingen over het hoofd? Zijn er dingen die beter kunnen ? Is het strategy pattern hier 'overkill', ...

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
Je kan het inderdaad doen met een strategy design pattern. Maar wat ik dan een beetje onduidelijk vind is waarom je een detail werking zou moeten meegeven aan het loggen als je eigelijk wilt dat de gehele werking anders is.

Ik zou persoonlijk gaan voor een Log 'Factory'. Je maakt een interface Log (en niet met die vervelende abstracte classes knoeien omdat je zoveel interfaces kan implementeren als je maar wilt, maar classes kan je in c# maar 1). En je maakt daarvan een x-aantal implementaties.

interface Log{
...void startLogging();
...void writeLog();
...void endLogging();
}

abstract class AbstractLog{
...void startLogging(){...}
...void writeLog(){...}
...void endLogging(){...}
}

class ToDatabaseLog extends AbstractLog{
...etc etc etc
}

class ToFileLog implements Log{
...void startLogging(){...}
...void writeLog(){...}
...void endLogging{...}
}

class LogFactory{
...static Log createLogger(){return new LogToDatabase();}
}


en als je dan een andere logger wilt hebben, dan kan je bij die factory gewoon een return new ToFileLog() terug sturen. Hierdoor heb je dus centraal object opbouw staan. Je moet dan even kijken bij factory design pattern.

En verder vind ik het gebruik van design patterns mits het helderheid verschaft, juist een must.

Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Geen matches
Kan je niet een class maken die ipv een string een Exception verwacht? Dan zou je op basis van polymorphisme kunnen bepalen of iets danwel naar een database danwel naar een file wordt geschreven. Bovendien wordt je dan ook gedwongen meer met exceptions te werken.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Geen matches
Ik heb mischien nog wel een aantal tips mbt de logger :). Kijk ook eens naar andere implementaties. Bij mij op het werk gebruiken we een uitgebreide variant van log4j. Hiervoor hebben we een wrapper geschreven die nog extra dingen toevoegd.

Zorg dat je in je applicatie zelf zo min mogelijk met je error statements moet doen. Geef desnoods met de constructor de naam van de class mee (of met de getInstance waneer je gebruik maakt van een factory). In principe zou je zo min mogelijk moeten doen met je logger binnen je eigen class. Alleen de log.error() oid. In de logger kun je vervolgens wel de classnaam, het tijdstip en andere relevante info toevoegen.

Daarnaast raad ik je aan om ook een log.info en log.debug oid toe te voegen. Dan kun je in je logger aangeven wel 'loglevel' je wilt gebruiken. Erg handig waneer er wat mis lijkt te gaan. Dan zet je je level ff op debug en kun je gaan debuggen :). Vergeet trouwens niet dat het erg handig is waneer je naast een string ook een exception mee kunt geven (geen id of dat in C# zit. Ben beter bekend met java). Dan kun je in je logs ook een stacktrace neerzetten :).

Verder zou ik mbt het wegschrijven zo min mogenlijk in de logger zelf zetten. Hierin dus geen db-connectie of bestand, maar gewoon implementaties die een methode writeLn(timestamp, string) hebben. Je zult de velden een beetje moeten opsplitsen zodat een db bv in verschillende kolomen kan schrijven en een bestand wat leuk kan worden uitgelijnd.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Geen matches
En je wilt misschien wel ook categorieeen erin aanbrengen. Debug messages, Warnings, Errors. Sommige moeten wel gelogd worden, sommigen niet. Maar dit is allemaal ter uitbereiding.

Je pattern lijkt me juist gekozen en goed geimplementeerd. Ik zou ook alleen idd, zoals Alarmnummer zegt, gaan voor een combinatie met een factory pattern of singleton voor de instantie het log object zelf.

We adore chaos because we like to restore order - M.C. Escher


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Orphix schreef op 22 oktober 2002 @ 11:41:
Kan je niet een class maken die ipv een string een Exception verwacht? Dan zou je op basis van polymorphisme kunnen bepalen of iets danwel naar een database danwel naar een file wordt geschreven. Bovendien wordt je dan ook gedwongen meer met exceptions te werken.
Afgezien van de exceptions, werk je in mijn ontwerp inderdaad ook met polymorphisme :) We zitten dus op dezelfde lijn en persoonlijk vind ik het strategy design pattern meer voor detail gedrag geschikt en daar is hier geen sprake van (zou wel kunnen hoor). vb.

interface Writer{
...void writeLine(String line);
}

class FileWriter implements Writer{
...void writeLine(String line){...}
}

class DatabaseWriter implements Writer{
...void writeLine(String line){...}
}

class Logger{
...private Writer _writer;
...public Logger(Writer writer){
......_writer = writer;
...}

...public void writerError(String message){
......_writer.writeLine("error on "+getDate());
......_writer.writeLine(message);
...}
}

Op deze manier bepaal je het detail gedrag van de logger mbv de writer en dan heb kan je dus wel gebruik maken van het strategy design pattern.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
[nohtml]
Alarmnummer schreef op 22 oktober 2002 @ 11:34:
Je kan het inderdaad doen met een strategy design pattern. Maar wat ik dan een beetje onduidelijk vind is waarom je een detail werking zou moeten meegeven aan het loggen als je eigelijk wilt dat de gehele werking anders is.
Je bedoelt de BeginLog, WriteError en StopLog methods in de klasse Logger?
Die implementeren geen detail werking, die roepen gewoon op hun beurt de respectievelijke AbstractLog::StartLogging, AbstractLog::WriteLog, ... functie aan.
Ik zou persoonlijk gaan voor een Log 'Factory'. Je maakt een interface Log (en niet met die vervelende abstracte classes knoeien omdat je zoveel interfaces kan implementeren als je maar wilt, maar classes kan je in c# maar 1). En je maakt daarvan een x-aantal implementaties.
De reden waarom ik het met een abstract class doe , is dat ik dan als volgt polymorphisme kan afdwingen:
code:
1
AbstractLog logger = new LogToFile()


Maar goed, ik zal eens kijken hoe ik dat met interfaces kan doen. Het AbstractFactory pattern heb ik nog niet bekeken en ik heb m'n boek hier ook niet. Dat zal ik morgen ofzo eens bekijken.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
whoami schreef op 22 oktober 2002 @ 11:52:
[nohtml]
[...]
Je bedoelt de BeginLog, WriteError en StopLog methods in de klasse Logger?
Die implementeren geen detail werking, die roepen gewoon op hun beurt de respectievelijke AbstractLog::StartLogging, AbstractLog::WriteLog, ... functie aan.
Ik zou dan echt gaan werken met polymorphisme. Anders moet je mijn reply hiervoor nog even bekijken.
De reden waarom ik het met een abstract class doe , is dat ik dan als volgt polymorphisme kan afdwingen:
code:
1
AbstractLog logger = new LogToFile()
Jij werkt dan inderdaad ook met polymorhisme. Maar jouw 'Logger' class doet niets anders dan alle methode aanroepen delegeren naar die AbstractLog familie en heeft zelf absoluut geen toegevoegde waarde. Ik zou die dus gewoon verwijderen.
Maar goed, ik zal eens kijken hoe ik dat met interfaces kan doen.
Het voordeel als je werkt via interfaces is dat je een class zoveel interfaces kan laten implementeren als nodig is en hij kan maar 1 class implementeren. Als je ontwerp via interfaces verkreeg je een enorm stuk bewegingsvrijheid en je hoeft je class hierarchieen niet zo te verneuken.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Orphix schreef op 22 oktober 2002 @ 11:41:
Kan je niet een class maken die ipv een string een Exception verwacht? Dan zou je op basis van polymorphisme kunnen bepalen of iets danwel naar een database danwel naar een file wordt geschreven. Bovendien wordt je dan ook gedwongen meer met exceptions te werken.


Hmmm... Da's zeker een idee, maar ben je dan niet wat minder flexibel? Ik had gedacht om de logger als volgt te gebruiken:
code:
1
2
3
4
5
6
7
8
try
{
  ....
}
catch ( SqlException e )
{
  Logger.WriteError ( e.Message );
}


Ik kan natuurlijk de WriteError method wel overloaden, dat er zowel een Exception als een string kan meegegeven worden.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Geen matches
Ik ben bang dat we elkaar niet helemaal goed hebben begrepen. Ik interpreteerde de vraag zo dat de ene error (bv InvalidPasswordException) wel naar de database geschreven moest worden en een andere error (bv InvalidObjectException) juist weer naar een bestand geschreven moest worden.
Alarmnummer (en anderen geloof ik ook :+) hebben het zo opgevat dat alles of naar de database gaat of naar een bestand. In dat geval is mijn oplossing niet echt praktisch.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
[nohtml]
Alarmnummer schreef op 22 oktober 2002 @ 11:57:
[...]

Ik zou dan echt gaan werken met polymorphisme. Anders moet je mijn reply hiervoor nog even bekijken.
Ik zie dat je in die reply een instance maakt van een interface.
* whoami wist niet dat dat kon :?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Orphix schreef op 22 oktober 2002 @ 12:02:
Ik ben bang dat we elkaar niet helemaal goed hebben begrepen. Ik interpreteerde de vraag zo dat de ene error (bv InvalidPasswordException) wel naar de database geschreven moest worden en een andere error (bv InvalidObjectException) juist weer naar een bestand geschreven moest worden.
Alarmnummer (en anderen geloof ik ook :+) hebben het zo opgevat dat alles of naar de database gaat of naar een bestand. In dat geval is mijn oplossing niet echt praktisch.
KISS ;)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Orphix schreef op 22 oktober 2002 @ 12:02:
Ik ben bang dat we elkaar niet helemaal goed hebben begrepen. Ik interpreteerde de vraag zo dat de ene error (bv InvalidPasswordException) wel naar de database geschreven moest worden en een andere error (bv InvalidObjectException) juist weer naar een bestand geschreven moest worden.
Alarmnummer (en anderen geloof ik ook :+) hebben het zo opgevat dat alles of naar de database gaat of naar een bestand. In dat geval is mijn oplossing niet echt praktisch.


Het is idd zo dat alles of naar de databank, of naar een file moet worden weggeschreven. Er wordt geen onderscheid gemaakt van : die dingen moeten naar de db, die errors naar een file.
Het is wel zo dat , als de databankconnectie wegvalt oid, en de errors dus niet meer naar de db kunnen gelogged worden, de logger ze naar een file moet wegschrijven.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 22 oktober 2002 @ 12:02:
[nohtml]
[...]

Ik zie dat je in die reply een instance maakt van een interface.
* whoami wist niet dat dat kon :?
Je kan inderdaad geen instanties aanmaken van een interface. Ik heb even zitten kijken want ik maak ook wel eens een fout, maar ik heb niets gevonden :) Waar doe ik dat?

en weet je trouwens dat dit ook kan?

interface A{}
interface B extends A{}

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 22 oktober 2002 @ 12:05:
[...]

Je kan inderdaad geen instanties aanmaken van een interface. Ik heb even zitten kijken want ik maak ook wel eens een fout, maar ik heb niets gevonden :) Waar doe ik dat?


Hier:
Alarmnummer schreef op 22 oktober 2002 @ 11:46:

interface Writer{
...void writeLine(String line);
}

class Logger{
...private Writer _writer;
...public Logger(Writer writer){
......_writer = writer;
...}

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik maak daar geen instantie aan hoor :)

Je kan het volgende zeggen:

Logger logger = new Logger(new DatabaseWriter());

maar omdat databaseWriter aan de Writer interface voldoet, weet ik dat in Logger alles mbv polymorphisme opgelost gaat worden :)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 22 oktober 2002 @ 12:08:
[...]

Ik maak daar geen instantie aan hoor :)

Je kan het volgende zeggen:

Logger logger = new Logger(new DatabaseWriter());

maar omdat databaseWriter aan de Writer interface voldoet, weet ik dat in Logger alles mbv polymorphisme opgelost gaat worden :)


Dan snap ik het niet.
Writer is in jouw voorbeeld toch een interface.
met deze code:
code:
1
private Writer _writer;

maak je toch een instance van Writer?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 22 oktober 2002 @ 13:06:
Dan snap ik het niet.
Writer is in jouw voorbeeld toch een interface.
met deze code:
code:
1
private Writer _writer;

maak je toch een instance van Writer?
Nee hoor. Ik declareer daar een member van het type Writer en daar kan dus een class in komen te staan die die Writer interface implementeerd. En dat zijn in dit geval FileWriter en DatabaseWriter. En die waarde wordt dus ingevuld via de constructor van Logger. Je geeft daar een implementatie van de Writer interface mee als argument.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
Alarmnummer schreef op 22 oktober 2002 @ 13:09:
[...]

Nee hoor. Ik declareer daar een member van het type Writer en daar kan dus een class in komen te staan die die Writer interface implementeerd. En dat zijn in dit geval FileWriter en DatabaseWriter. En die waarde wordt dus ingevuld via de constructor van Logger. Je geeft daar een implementatie van de Writer interface mee als argument.


Ah ok. Idd, het is geen instance. Het is dan eigenlijk net alsof ik:
code:
1
private AbstractLog logger;

geschreven heb, waar AbstractLog een abstracte class is.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
whoami schreef op 22 oktober 2002 @ 13:12:

[...]


Ah ok. Idd, het is geen instance. Het is dan eigenlijk net alsof ik:
code:
1
private AbstractLog logger;

geschreven heb, waar AbstractLog een abstracte class is.
Yep. Maar het vervelende aan abstracte classes is dat je nooit van meerdere tegelijk kan overerven en met interfaces hou je bewegingsvrijheid.

Als je wel de behoefte om code te gaan sharen dan kan je de volgende aanpak daarvoor gebruiken:


interface Log{}

abstract class AbstractLog{}

class DatabaseLog extends AbstractLog{}

class FileLog extends AbstractLog{}

Je kan nu code gaan sharen via de AbstractLog.

maar als je geen behoefte hebt aan dat code sharen bij bv de screen log, dan kan je het volgende doen:

class ScreenLog implements Log{}

Je weet dat alles implementaties voldoen aan die Log interface, en hoe dat op de achtegrond wordt afgehandeld is van buitenaf totaal niet interessant.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
[nohtml]
Alarmnummer schreef op 22 oktober 2002 @ 13:15:
[...]

Yep. Maar het vervelende aan abstracte classes is dat je nooit van meerdere tegelijk kan overerven
Dat vind ik nu zo geen probleem. Multiple Inheritance heb ik eigenlijk nog nooit nodig gehad.

* whoami gaat ff aan de slag.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
whoami schreef op 22 oktober 2002 @ 13:21:
Dat vind ik nu zo geen probleem. Multiple Inheritance heb ik eigenlijk nog nooit nodig gehad.
Ik vind het persoonlijk veel duidelijker ontwerpen. Implementatie is een bijzaak. Je kan gewoon gaan ontwerpen vanuit interfaces. Ik pas het zelf vrij veel toe omdat ik dus een hele duidelijke 'verwachte functionaliteit' heb, en hoe dat is geimplementeerd is bijzaak. abstracte classes zijn overgewardeerd :) Kijk anders maar eens bij java door de Collection framework of anders die van .NET. Je zult ook zien dat alles op deze manier is ontworpen en je daar erg veel vrijheid voor handen hebt.
whoami gaat ff aan de slag.
Post je resultaat hier ook even :)

ps: ik zou inderdaad een Singleton (zoals hierboven vermeld) gaan gebruiken voor je Logger.


class Logger{
...private static Logger s_instance;

...public static void createLogger(Writer writer){
......s_instance = new Logger(writer);
...}

...public static Logger getInstance(){
......return s_instance;
...}

...private Writer _writer;

...private Logger(Writer writer){
......_writer = writer;
...}
}

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 22 oktober 2002 @ 13:23:
Post je resultaat hier ook even :)
Zal ik zeker doen.
ps: ik zou inderdaad een Singleton (zoals hierboven vermeld) gaan gebruiken voor je Logger.


class Logger{
...private static Logger s_instance;

...public static void createLogger(Writer writer){
......s_instance = new Logger(writer);
...}

...public static Logger getInstance(){
......return s_instance;
...}

...private Writer _writer;

...private Logger(Writer writer){
......_writer = writer;
...}
}


Ik heb het GoF boek niet bij de hand, en kan het dus niet ff opzoeken daarin.
Maar in die class Logger hou je dus een instance bij van de class Logger zelf.
Ga je hierdoor zorgen dat er slechts 1 instance van de errorlogger in het programma kan gestaan oid?

En dan ga je de class alsvolgt gebruiken als ik het goed heb:
code:
1
2
3
Logger.getInstance().StartLogging();
Logger.getInstance().WriteLog();
...

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 22 oktober 2002 @ 14:15:
Maar in die class Logger hou je dus een instance bij van de class Logger zelf.
yep
Ga je hierdoor zorgen dat er slechts 1 instance van de errorlogger in het programma kan gestaan oid?
Yep. Van een Singleton kan je garanderen dat er maar 1 instantie van wordt aangemaakt. Gewoonlijk is dit de aanpak:

class A{
...private static A s_instance;

...public static A getInstance(){
......if(s_instance == null){
.........s_instance = new A();
......}
......return s_instance;
...}

...private A(){}
}
En dan ga je de class alsvolgt gebruiken als ik het goed heb:
[code]
Logger.getInstance().StartLogging();
Logger.getInstance().WriteLog();
Zo kan het idd. Maar ik doe meestal het volgende als ik meer acties achter elkaar aanroep.

Logger logger = Logger.getInstance();
logger.log("blaat1");
logger.log("blaat2"):

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
Ik heb het ff aangepast. Ipv een abstract class gebruik ik nu een interface. De LogWriter classes implementeren die interface.

Afbeeldingslocatie: http://users.pandora.be/fgzone/schema2.jpg

Toch denk ik dat er nog iets schort aan die ErrorLogger class.
* whoami gaat thuis eens dat Singleton / AbstractFactory pattern eens bestuderen.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Janoz schreef op 22 oktober 2002 @ 11:44:
Ik heb mischien nog wel een aantal tips mbt de logger :). Kijk ook eens naar andere implementaties. Bij mij op het werk gebruiken we een uitgebreide variant van log4j. Hiervoor hebben we een wrapper geschreven die nog extra dingen toevoegd.
Ik heb die log4j eens gedowned maar nog niet bekeken. Thx anyway.
Vergeet trouwens niet dat het erg handig is waneer je naast een string ook een exception mee kunt geven (geen id of dat in C# zit. Ben beter bekend met java). Dan kun je in je logs ook een stacktrace neerzetten :).
Tuurlijk zit dat in C#. C# is geen ketters ding hoor. ;)
Verder zou ik mbt het wegschrijven zo min mogenlijk in de logger zelf zetten. Hierin dus geen db-connectie of bestand, maar gewoon implementaties die een methode writeLn(timestamp, string) hebben.

Wat bedoel je hier precies? Ik heb in m'n errorlogger geen db-connectie of bestand. Deze zitten in de classes DatabaseLogWriter en FileLogWriter.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 22 oktober 2002 @ 15:43:
[nohtml]
Wat bedoel je hier precies? Ik heb in m'n errorlogger geen db-connectie of bestand. Deze zitten in de classes DatabaseLogWriter en FileLogWriter.
Hij bedoelt ermee dat je specifieke dingen in een generiek object gaat plaatsen. Als je een n aantal implementaties wilt maken, dan is dat bij jouw 1e logger aanpak niet mogelijk. Omdat daar gegevens staan van iedere aanpak. Je mag dat generieke logger object dus niet besmetten met specifieke code. (Dit gaat dus over je 1e ontwerp).

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
whoami schreef op 22 oktober 2002 @ 15:30:
Toch denk ik dat er nog iets schort aan die ErrorLogger class.
* whoami gaat thuis eens dat Singleton / AbstractFactory pattern eens bestuderen.
Ik zat fout met die Factory design pattern omdat deze vooral handig als je centraal de opbouw wilt hebben van objecten. Aangezien je maar 1 object wil maken is een Singleton veel beter geschikt. Je kan dus altijd naar die factory kijken, maar is voor dit probleem minder interessant.

En wat vind je er aan schorten? Trouwens de aanpak die je nu hebt gebruik is dus mbv het strategy design pattern. Maar je zou ook een ontwerp kunnen maken die volledig is gemaakt op polymorphisme. Zie hiervoor mijn 1e reply (die factory even vergeten).

Je moet jezelf afvragen of een generieke werkinging van een object hebt, dat alleen verschilt in detail of als je een object hebt die volledig anders werkt.

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Je zou er zelfs ook nog voor kunnen kiezen om zelfs nog weer een logger interface te maken. Dan heb je weer een stuk ontoppeling tussen de implementatie in de interface. Hierdoor kan je nog makkelijker wijzigen :) *houd van interfaces en heeft weer eens te veel tijd over :P *

Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Geen matches
Alarmnummer schreef op 22 oktober 2002 @ 15:59:
Je zou er zelfs ook nog voor kunnen kiezen om zelfs nog weer een logger interface te maken. Dan heb je weer een stuk ontoppeling tussen de implementatie in de interface. Hierdoor kan je nog makkelijker wijzigen :) *houd van interfaces en heeft weer eens te veel tijd over :P *
eerm kiss?? :+

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
:P en ik hou trouwens ook meer van vrouwen ;)

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik wacht :P

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 22 oktober 2002 @ 15:51:

En wat vind je er aan schorten? Trouwens de aanpak die je nu hebt gebruik is dus mbv het strategy design pattern. Maar je zou ook een ontwerp kunnen maken die volledig is gemaakt op polymorphisme. Zie hiervoor mijn 1e reply (die factory even vergeten).

Je moet jezelf afvragen of een generieke werkinging van een object hebt, dat alleen verschilt in detail of als je een object hebt die volledig anders werkt.


Het strategy pattern werkt toch ook in zekere zin met polymorphisme. Je hebt in de 'context-class' (in m'n geval ErrorLogger) een verwijzing naar een object dat voldoet aan de ILogWriter interface. Dit object kan zowel DatabaseLogWriter als FileLogWriter zijn. De errorlog class gaat dan van het object dat voldoet aan de ILogWriter interface de methoden gaan aanroepen, zonder dat errorlog hoeft te weten of het nu een DatabaseLogWriter of een FileLogWriter object is.



Was gisteren niet thuis.... Sociale verplichtingen (vriendin enzow). ;)

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 23 oktober 2002 @ 09:05:
Het strategy pattern werkt toch ook in zekere zin met polymorphisme. Je hebt in de 'context-class' (in m'n geval ErrorLogger) een verwijzing naar een object dat voldoet aan de ILogWriter interface. Dit object kan zowel DatabaseLogWriter als FileLogWriter zijn. De errorlog class gaat dan van het object dat voldoet aan de ILogWriter interface de methoden gaan aanroepen, zonder dat errorlog hoeft te weten of het nu een DatabaseLogWriter of een FileLogWriter object is.
Het is inderdaad intern ook opgelost met polymorphisme. Maar je moet jezelf afvragen wat de toegevoegde waarde is van die ErrorLog class als iedere methode die op hem wordt aangeroepen toch wordt gedelageerd naar die ILogWriter.

Als er geen toegevoegde waarde is, dan zou ik hem dus verwijderen en rechtstreeks met die ILogWriter willen werken omdat je ontwerp anders onnodig complex is.

Als er meer wordt gedaan dan alleen delegeren, en eigelijk de werking alleen in detail verschilt (dus in jouw geval is het detail het medium waar je naar toe schrijft (db of file)) dan zou ik dmv een strategy design pattern oplossen zoals ik in een van mijn vorige berichten heb uitgelegd.

class Logger{
...private Writer _writer;
...public Logger(Writer writer){
......_writer = writer;
...}

...public void writerError(String message){
......_writer.writeLine("error on "+getDate());//toegevoegde waarde
......_writer.writeLine(message);
...}
}

Maar dat GoF boek bied je nieuwe oo bouwstenen waar je met andere mensen over kan praten. Ik vond dat er een hele nieuwe wereld voor me open ging. Naast basis constructies zoals for/while lussen, functies, arrays en methodes, krijg je er nog een hele reeks met constructies bij waar je makkelijk over kan discussieren. Het GoF boek vind ik dus een dikke aanrader voor iedereen :)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Bij het wegschrijven van de error komt er geen 'toegevoegde waarde' aan te pas.

't Probleem is wel, dat als er bv naar een databank gelogd wordt, en die databank is plotseling off-line, dat er dan naar een file moet kunnen verder gelogged worden. Die errorlogger zou dus dan zelf z'n DataBaseLogWriter moeten vervangen door een FileLogWriter.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Geen matches
whoami:

Bugtracker

kijk hier eens naar... specifiek in de Diagnostics folder

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 23 oktober 2002 @ 10:06:
't Probleem is wel, dat als er bv naar een databank gelogd wordt, en die databank is plotseling off-line, dat er dan naar een file moet kunnen verder gelogged worden. Die errorlogger zou dus dan zelf z'n DataBaseLogWriter moeten vervangen door een FileLogWriter.
Hmmzz.. ik ga zo ff fitnissen, maar volgens mij kan dit heel mooi gedaan worden met een state design pattern ;) Ik zal er eens over prakadenken :)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Hmmm. De requirements zijn aangepast.
Het moet nu idd mogelijk zijn om verschillende types errors/gebeurtenissen naar verschillende media te schrijven.
Om dit op te lossen moet aan de functie die opgeroepen wordt om de error weg te schrijven een parameter meegegeven worden die aangeeft of er naar de db, een file, ... moet gelogged worden.

M'n ontwerp ziet er nu voorlopig als volgt uit:
Afbeeldingslocatie: http://users.pandora.be/fgzone/schema3.jpg

Ik maak nog geen gebruik van het Singleton pattern, maar dat komt nog wel.
't Enige dat ik nog niet goed vind, is dat in de WriteLog method van de Logger class een case statement staat.
Adhv de meegegeven LogType parameter wordt het gepaste ILogwriter object aangemaakt. Dit wil dus zeggen dat, als er later een ILogWriter class bijkomt, ook de WriteLog method van Logger moet aangepast worden. (Het is wel gewoon maar die switch aanpassen, maar toch....).
Ik zou dat natuurlijk kunnen oplossen door, ipv een LogType parameter mee te geven een ILogWriter class mee te geven, maar ik vraag me af of dat kan.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik ben al met wat leuks bezig, ik zit alleen nog even met die logger class. Ik wou gaan dispatchen over logTypes, maar dan krijg ik in die logger een beperking op het aantal logtypes (gebruik een visitor) en dat wil ik niet. Ik moet nog even kijken hoe ik dat netjes ga oplossen.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 23 oktober 2002 @ 14:48:
Ik ben al met wat leuks bezig, ik zit alleen nog even met die logger class. Ik wou gaan dispatchen over logTypes, maar dan krijg ik in die logger een beperking op het aantal logtypes (gebruik een visitor) en dat wil ik niet. Ik moet nog even kijken hoe ik dat netjes ga oplossen.


* whoami zit nog zo ver niet in dat GoF boek :D
* whoami moet dringend eens verder lezen
* whoami heeft nog zoveel andere dingen te doen. :/

conclusie: * whoami komt tijd te kort.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Geen matches
code:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
/*
 * Original creation, Ben Houston [ www.exocortex.org ] under BSD license.
 * 
 * BSD Licence:
 * Copyright (c)2002,
 * Tran Khanh Hien[ codelib@websoftvn.com ]
 * Paul Gielens [ p.gielens@connexx.nl ]
 * WebSoft VN [www.websoftvn.com ]
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the WebSoft VN nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *  
 * =========================== CHANGE LOG ===========================
 * 
 * Sep 03, 2002 Paul Gielens [ p.gielens@connexx.nl ]
 * 
 *  - started change log
 *  - added comments
 *  - added trace level
 *  - added support for simple/advanced exception output
 *  - revised WriteExceptionRecord to support trace levels
 *  - added mail functionality
 * 
 * =========================== TO DO LIST ===========================
 * 
 *  - revise mail functionality for additional smtp server support
 */

using System;
using System.Diagnostics;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using System.Reflection;
using System.Resources;
using System.Data;
using System.Threading;
using System.Web;
using System.Web.Mail;


namespace Diagnostics
{
    /// <summary>
    /// Represents bugtracking system
    /// </summary>
    /// <remarks>
    /// This class offers several debugging, tracking/tracing methods.
    /// You can add Objects to a specific watchlist, witch will be watched during the objects lifetime.
    /// Automated error logging as well as raising exceptions are the main tasks of this class.
    /// </remarks>
    public class BugTracking
    {
        /// <summary>
        /// Our trace level (1-10), default level 10
        /// </summary>
        static protected int s_traceLevel = 10;
        /// <summary>
        /// List containing log entries
        /// </summary>
        static protected ArrayList  s_logEntries    = new ArrayList();
        /// <summary>
        /// Hash table containing objects to be watched
        /// </summary>
        static protected Hashtable  s_htWatches = new Hashtable();

        /// <summary>
        /// Enables / disables ritch exception viewer, switched via property. Default set to true
        /// </summary>
        static protected bool s_ritchExceptionView = true;

        /// <summary>
        /// Sets the SMTP server used by the BugTracking component
        /// </summary>
        
        protected const string  _GLOBAL_SMTPSERVER = "pmail.vnn.vn";
        
        /// <summary>
        /// Defines the to address regarding error reporting
        /// </summary>
        protected const string  _GLOBAL_TOADDRESS = "codelib@websoftvn.com";

        /// <summary>
        /// Defines the from address regarding error reporting
        /// </summary>
        protected const string  _GLOBAL_FROMADDRESS = "bugreporter@websoftvn.com";


        /// <summary>
        /// Catches the thread exception from the caller
        /// </summary>
        /// <param name="o">Object witch threw the exception</param>
        /// <param name="e">Thread exception event arguments</param>
        static public void OnThreadException( object o, ThreadExceptionEventArgs e )
        {
            BugTracking.LogException( e.Exception );
        }

        /// <summary>
        /// Displays a messagebox with the exception details and logs the exception in the error log
        /// </summary>
        /// <param name="e">Exception object</param>
        static public void LogException( Exception e )
        {
            string fileName = BugTracking.WriteExceptionRecord( e );
            switch (s_ritchExceptionView)
            {
                case false:             
                    System.Windows.Forms.MessageBox.Show( null,
                        "A fatal error occured.  Please contact your system administrator. See the log for details:\n" + 
                        fileName,
                        Application.ProductName,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error );
                    break;
                case true:
                    ExceptionView frmExceptionView = new ExceptionView(e);
                    frmExceptionView.ShowDialog();
                    break;
            }
        }

        /// <summary>
        /// Sends an error report using Simple Mail Transfer Protocol
        /// </summary>
        static public void SendBugReport()
        {
            MailMessage mMesg = new MailMessage();
            mMesg.From = _GLOBAL_FROMADDRESS;
            mMesg.To = _GLOBAL_TOADDRESS;
            mMesg.Subject = "Code Library Error Report";
            mMesg.Body = "See attachement for stack trace.";                
            mMesg.Attachments.Add(new MailAttachment(Application.StartupPath + "\\error.log", MailEncoding.Base64));
            SmtpMail.SmtpServer = _GLOBAL_SMTPSERVER;
            SmtpMail.Send(mMesg);
            
        }

        /// <summary>
        /// Represents helper class for the bugtracking class, this class generates some entry details
        /// </summary>
        protected class LogEntry
        {
            /// <summary>
            /// Contains the log entry details
            /// </summary>
            public string       Text;
            /// <summary>
            /// Contains date and time of log entry
            /// </summary>
            public DateTime     DateTime;
        
            /// <summary>
            /// Retrieves the log entry details
            /// </summary>
            /// <param name="text"></param>
            public LogEntry( string text )
            {
                this.Text       = text;
                this.DateTime   = DateTime.Now;
            }
            
            /// <summary>
            /// String represations of log entry details
            /// </summary>
            /// <returns>Log entry details</returns>
            public override string  ToString()
            {
                return  "[" + this.DateTime.ToLocalTime() + "] " + this.Text;
            }
        }

        /// <summary>
        /// Adds a log entry to the entry list
        /// </summary>
        /// <param name="text">Contains entry details</param>
        static public void Log( string text )
        {
            s_logEntries.Add( new LogEntry( text ) );
        }

        /// <summary>
        /// Orders the bugtracker to keep an eye on this object
        /// </summary>
        /// <param name="name">Object name</param>
        /// <param name="value">Object value</param>
        static public void  SetWatch( string name, object value )
        {
            Debug.Assert( name != null );
            if( s_htWatches.Contains( name ) )
            {
                s_htWatches.Remove( name );
            }

            s_htWatches.Add( name, ( value != null ) ? new WeakReference( value ) : null );
            Debug.Assert( s_htWatches.Contains( name ) == true );
        }

        /// <summary>
        /// Order bugtracker to stop watching the object
        /// </summary>
        /// <param name="name">Object name</param>
        static public void  RemoveWatch( string name )
        {
            Debug.Assert( name != null );
            Debug.Assert( s_htWatches.Contains( name ) == true );
            
            s_htWatches.Remove( name );
        }

        /// <summary>
        /// Retrieve the watch string for the given object
        /// </summary>
        /// <param name="name">Object name</param>
        /// <returns>String witch hold the watch information for the given object</returns>
        static public string GetWatchString( string name )
        {
            Debug.Assert( name != null );
            Debug.Assert( s_htWatches.Contains( name ) == true );
            
            WeakReference wr = (WeakReference) s_htWatches[ name ];
            if( wr != null )
            {
                if( wr.IsAlive == true )
                {
                    object value = wr.Target;
                    return  value.ToString() + " [" + value.GetType().Name + "]";
                }
                else
                {
                    return  "(garbageCollected)";
                }
            }
            else
            {
                return  "(null)";
            }
        }

        /// <summary>
        /// Our trace level switch for the outside world
        /// </summary>
        static public int TraceLevel
        {
            get 
            {
                return s_traceLevel;                
            }
            set
            {
                // Our trace level exist within 1-10
                if (value > 0 && value < 11)
                s_traceLevel = value;
            }
        }

        /// <summary>
        /// Enable / disable ritch exception view
        /// </summary>
        static public bool RitchExceptionView
        {
            set
            {
                    s_ritchExceptionView = value;
            }
        }

        /// <summary>
        /// Write the exception record to the application error log
        /// </summary>
        /// <param name="e">Exception object</param>
        /// <returns>Filename where we added the bugtracking info</returns>
        /// <remarks>We should implent the trace levels in here witch can be set via a propertie, PG
        /// </remarks>
        static public string WriteExceptionRecord( Exception e )
        {
            try
            {
                string  fileName = Path.Combine( Application.StartupPath, "error.log" );
                StreamWriter sw = new StreamWriter( fileName, true );

                // Trace Level 1
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 1 )
                {               
                    sw.WriteLine( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" );

                    try
                    {
                        DateTime now = DateTime.Now;
                        sw.WriteLine( "CurrentDate: " + now.ToLongDateString() );
                        sw.WriteLine( "CurrentTime: " + now.ToLongTimeString() );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        // Write the current date and time to log
                        sw.WriteLine( "<error-CurrentDateTime>" + ex.ToString() );
                    }
                    
                    try
                    {
                        // Write some standard info regarding the exception
                        sw.WriteLine( "Exception.Type: " + e.GetType().Name );
                        sw.WriteLine( "Exception.Message: " + e.Message );
                        sw.WriteLine( "Exception.Source: " + e.Source );
                        sw.WriteLine( "Exception.HelpLink: " + e.HelpLink );
                        sw.WriteLine( "Exception.TargetSite: " + e.TargetSite );
                        sw.WriteLine( "Exception.StackTrace: " );
                        sw.WriteLine( e.StackTrace );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-Exception>" + ex.ToString() );
                    }
                }

                // Trace Level 2
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 2 )
                {
                    try
                    {
                        // Write the total mem to log
                        sw.WriteLine( "GC.TotalMemory: " + GC.GetTotalMemory( false ) );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-GC>" + ex.ToString() );
                    }
                }
        
                // Trace Level 3
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 3 )
                {   
                    try
                    {
                        // Let our service engineer know with product is causing the exception by logging this info
                        sw.WriteLine( "Application.ProductName: " + Application.ProductName );
                        sw.WriteLine( "Application.ProductVersion: " + Application.ProductVersion );
                        sw.WriteLine( "Application.StartupPath: " + Application.StartupPath );
                        sw.WriteLine( "Application.ExecutablePath: " + Application.ExecutablePath );
                        sw.WriteLine( "Application.CurrentDirectory: " + Directory.GetCurrentDirectory() );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-Application>" + ex.ToString() );
                    }
                }
        
                // Trace Level 4
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 4 )
                {   
                    try
                    {
                        // N-tier debugging, valueable info!!!
                        Assembly execAssembly = Assembly.GetExecutingAssembly();
                        sw.WriteLine( "ExecutingAssembly.CodeBase: " + execAssembly.CodeBase );
                        sw.WriteLine( "ExecutingAssembly.Location: " + execAssembly.Location );
                        sw.WriteLine( "ExecutingAssembly.GlobalAssemblyCache: " + execAssembly.GlobalAssemblyCache );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-ExecutingAssembly>" + ex.ToString() );
                    }
                }

                // Trace Level 5
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 5 )
                {   
                    try
                    {
                        foreach( string watchName in s_htWatches.Keys )
                        {
                            sw.WriteLine( "Watch[" + watchName + "]: " + GetWatchString( watchName ) );
                        }
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-Watches>" + ex.ToString() );
                    }
                }

                // Trace Level 6
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 6 )
                {   
                    try
                    {
                        // We traced the exception so grabt he details from the enty list
                        foreach( LogEntry logEntry in s_logEntries )
                        {
                            sw.WriteLine( "LogEntry" + logEntry.ToString() );
                        }
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-LogEntry>" + ex.ToString() );
                    }
                }

                // Trace Level 7
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 7 )
                {   
                    try
                    {
                        // Assembly details to provide detailed info for N-tier debugging
                        Assembly selfAssembly = Assembly.GetAssembly( typeof( BugTracking ) );
                        sw.WriteLine( "CurrentAssembly.CodeBase: " + selfAssembly.CodeBase );
                        sw.WriteLine( "CurrentAssembly.Location: " + selfAssembly.Location );
                        sw.WriteLine( "CurrentAssembly.GlobalAssemblyCache: " + selfAssembly.GlobalAssemblyCache );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-CurrentAssembly>" + ex.ToString() );
                    }
                }

                // Trace Level 8
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 8 )
                {   
                    try
                    {
                        // Thread details
                        Thread thread = Thread.CurrentThread;
                        sw.WriteLine( "CurrentThread.Name: " + thread.Name );
                        sw.WriteLine( "CurrentThread.Priority: " + thread.Priority );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-CurrentThread>" + ex.ToString() );
                    }
                }

                // Trace Level 9
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 9 )
                {   
                    try
                    {
                        // Process details
                        Process process = Process.GetCurrentProcess();
                        sw.WriteLine( "CurrentProcess.Name: " + process.ProcessName );
                        sw.WriteLine( "CurrentProcess.MachineName: " + process.MachineName );
                        sw.WriteLine( "CurrentProcess.MainModule: " + process.MainModule );
                        sw.WriteLine( "CurrentProcess.StartDate: " + process.StartTime.ToLongDateString() );
                        sw.WriteLine( "CurrentProcess.StartTime: " + process.StartTime.ToLongTimeString() );
                        sw.WriteLine( "CurrentProcess.UserProcessorTime: " + process.UserProcessorTime );
                        sw.WriteLine( "CurrentProcess.TotalProcessorTime: " + process.TotalProcessorTime );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-CurrentProcess>" + ex.ToString() );
                    }
                }

                // Trace Level 10
                //--------------------------------------------------------------------------------
                if (s_traceLevel >= 10 )
                {   
                    try
                    {
                        // Grab the customers OS info in case they upgraded without us knowing
                        OperatingSystem os = Environment.OSVersion;
                        sw.WriteLine( "Environment.OSVersion.Platform: " + os.Platform );
                        sw.WriteLine( "Environment.OSVersion.Version: " + os.Version );
        
                        Version ver = Environment.Version;
                        sw.WriteLine( "Environment.Version.Major: " + ver.Major );
                        sw.WriteLine( "Environment.Version.Minor: " + ver.Minor );
                        sw.WriteLine( "Environment.Version.Revision: " + ver.Revision );
                        sw.WriteLine( "Environment.Version.Build: " + ver.Build );

                        sw.WriteLine( "Environment.UserName: " + Environment.UserName );
                        sw.WriteLine( "Environment.SystemDirectory: " + Environment.SystemDirectory );
                        sw.WriteLine( "Environment.TickCount: " + Environment.TickCount );
                        sw.WriteLine( "Environment.CommandLine: " + Environment.CommandLine );
                        string[] args = Environment.GetCommandLineArgs();
                        if( args != null )
                        {
                            for( int i = 0; i < args.Length; i ++ )
                            {
                                sw.WriteLine( "Environment.CommandLineArgs[" + i + "]: " + args[i] );
                            }
                        }
                        sw.WriteLine( "Environment.StackTrace: " );
                        sw.WriteLine( Environment.StackTrace );
                        sw.Flush();
                    }
                    catch( Exception ex )
                    {
                        sw.WriteLine( "<error-Environment>" + ex.ToString() );
                    }
                }

                sw.WriteLine( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
                sw.Close();
                
                return  fileName;
            }
            catch( Exception )
            {
                return  "-- error writing log file --";
            }
        }
    }
}


Zo dan...

code:
1
BugTracking.LogException(ex);



code:
1
static public string WriteExceptionRecord( Exception e )


Lijkt me ideaal om uit te breiden... jullie willen het aanzienlijk moeilijker maken dan het is ;)

Uit de stacktrace kun je halen wat voor runtime probleem je hebt...daarop kun je dan in een switch op de juiste maniet de zaken wegschrijven. Patterns zijn erg leuk, maar als ik naar de lading UML zit te kijken hierboven denk ik dat je het doel voorbij aan het gaan bent!

Nogmaals... hier vind je een pratische implementatie. Ook is een profiler meegeleverd welke ik gebruik voor bugtracking in gedistribueerde omgevingen.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
paulgielens: thx, ik zal het zeker eens bekijken.

Waarom ik dat pattern gebruik: bepaalde events moeten naar een db gelogged worden, andere weer naar een textfile, nog andere naar de eventlogger, etc.... Eventueel kan dat later nog uitgebreid worden.
Het is ook de bedoeling dat er niet enkel errors gelogged worden, maar dat er ook bepaalde gebeurtenissen kunnen gelogged worden. Bv: user A heeft aangelogd om x uur, user B heeft klant x gewijzigd, .... )

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Deze code voldoet niet aan zijn specs. Hier heb je dus niet zo veel aan.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Geen matches
whoami schreef op 23 oktober 2002 @ 15:42:
Waarom ik dat pattern gebruik: bepaalde events moeten naar een db gelogged worden, andere weer naar een textfile, nog andere naar de eventlogger, etc....
Ja begrijp ik, maar kijk nu eens goed naar je UML... dit is gewoon te gek voor woorden, man o man. Het is in feite niets meer als de stacktrace goed intrepeteren en daarop volgend de juiste manier van logging toepassen.
Eventueel kan dat later nog uitgebreid worden.
WriteExceptionRecordToDB(Exception ex)
WriteExceptionRecordToXML(Exception ex)
WriteExceptionRecordToFile(Exception ex)
WriteExceptionRecordToEventLog(Exception ex)
WriteExceptionRecordToMailQueue(Exception ex)

Vat je een beetje mijn idee d'r achter?
Het is ook de bedoeling dat er niet enkel errors gelogged worden, maar dat er ook bepaalde gebeurtenissen kunnen gelogged worden. Bv: user A heeft aangelogd om x uur, user B heeft klant x gewijzigd, .... )
Dit is een typisch voorbeeld van Asserts, conditional debugging

code:
1
2
3
4
5
6
7
[edit]
[Conditional("Debug")]
[/edit]
void SignIn(string name, string pwd)
{
  Debug.WriteLineIf( objClientManager(name, pwd)!=0, "User A heeft ingelogd om" + this.DateTime.ToLocalTime() );
}


Kijk eens goed naar Runtime Debugging en dan met name, Conditional Debugging, Runtime Tracing, Making Assertions. Kijk voor de grap ook eens even wat wel/niet sealed is in het .NET FrameWork...

[ Voor 0% gewijzigd door Scare360 op 23-10-2002 15:59 . Reden: bijna het belangrijkste regeltje code vergeten! ]


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik kwam op het volgende uit. Vrij minimaal en alles wat onnodig was heb ik eraf gestript. Ik heb troubens niet gekozen voor een generieke logger class maar een specifieke omdat je misschien wat variatie aan wilt brengen in je log mogelijkheden? Desnoods kan je hem natuurlijk nog wel een generieke maken.

code:
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public interface Writer{
    public void write(String error);
    public void write(Exception exception);
}

public class DatabaseLogWriter implements Writer{
    
    private Writer _errorWriter;
    
    //zie state design pattern
    private Writer _writer;

    public DatabaseLogWriter(Writer errorWriter){
    _errorWriter = errorWriter;
    _writer = new InternalDatabaseLogWriter();
    }

    public void write(String error){_writer.write(error);}
    public void write(Exception exception){_writer.write(exception);}

    private class InternalDatabaseLogWriter implements Writer{
    public void write(String error){
        try{
        //database stuff
        }catch(SQLException e){
        //afhandelen db problemen

        //en je gaat nu naar file schrijven (dus andere state)
        _writer = _errorWriter;
        }
    }

    public void write(Exception exception){
        try{
        //database stuff
        }catch(SQLException e){
        //afhandelen db problemen

        //en je gaat nu naar file schrijven (dus andere state)
        _writer = _errorWriter;
        }
    }
    }
}

public class FileLogWriter implements Writer{
    public void write(String error){}
    public void write(Exception exception){}
}

public class XMLLogWriter implements Writer{
    public void write(String error);
    public void write(Exception exception){}
}


public class EenSpecifiekeLogger{
    private static EenSpecifiekeLogger s_instance;

    public static void createInstance(DatabaseLogWriter d, XMLLogWriter x, FileLogWriter f){
    if(s_instance!=null)
        throw new RuntimeException("eenSpecifiekeLogger already exists");
    s_instance = new EenSpecifiekeLogger(d,x,f);
    }

    public static EenSpecifiekeLogger getInstance(){return s_instance;}

    private DatabaseLogWriter _databaseLogWriter;
    private XMLLogWriter _xmlLogWriter;
    private FileLogWriter _fileLogWriter;

    private EenSpecifiekeLogger(DatabaseLogWriter d, XMLLogWriter x, FileLogWriter f){
    _databaseLogWriter = d;
    _xmlLogWriter = x;
    _fileLogWriter = f;
    }

    public DatabaseLogWriter getDatabaseLogWriter(){return _databaseLogWriter;}
    public XMLLogWriter getXMLLogWriter(){return _xmlLogWriter;}
    public FileLogWriter getFileLogWriter(){return _fileLogWriter;}
}

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
[nohtml]
paulgielens schreef op 23 oktober 2002 @ 15:56:
[...]


Ja begrijp ik, maar kijk nu eens goed naar je UML... dit is gewoon te gek voor woorden, man o man. Het is in feite niets meer als de stacktrace goed intrepeteren en daarop volgend de juiste manier van logging toepassen.
Nou, 't kan aan mij liggen, maar ik vind het redelijk eenvoudig en begrijpbaar.
WriteExceptionRecordToDB(Exception ex)
WriteExceptionRecordToXML(Exception ex)
WriteExceptionRecordToFile(Exception ex)
WriteExceptionRecordToEventLog(Exception ex)
WriteExceptionRecordToMailQueue(Exception ex)

Vat je een beetje mijn idee d'r achter?
Hum ja.... Dan gaat uw class-hierarchy wel eenvoudiger zijn, ....
Dit is een typisch voorbeeld van Asserts, conditional debugging
Niet echt, asserts is enkel in debugging.
Het loggen van gebeurtenissen moet hier ook in release gebeuren. Zie het als een soort auditing.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
paulgielens schreef op 23 oktober 2002 @ 15:56:
[...]


Ja begrijp ik, maar kijk nu eens goed naar je UML... dit is gewoon te gek voor woorden, man o man.
Dus goed ontwerpen is tegenwoordig niet meer nodig?
Het is in feite niets meer als de stacktrace goed intrepeteren en daarop volgend de juiste manier van logging toepassen.
:?
WriteExceptionRecordToDB(Exception ex)
WriteExceptionRecordToXML(Exception ex)
WriteExceptionRecordToFile(Exception ex)
WriteExceptionRecordToEventLog(Exception ex)
WriteExceptionRecordToMailQueue(Exception ex)

Vat je een beetje mijn idee d'r achter?
Ja.. dit heet ook wel een monolyth (en dat is dus slecht ;) )
Dit is een typisch voorbeeld van Asserts, conditional debugging
Dit heeft niets te maken met asserts en conditional debugging. Allerlei informatie moet gemeld worden en dat kan ook 'normale' info zijn.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Geen matches
ikke onder vuur ;)
Ja.. dit heet ook wel een monolyth (en dat is dus slecht )
Nou zo slecht is dit ook weer niet.

code:
1
2
3
4
5
switch (mijn_state)
{
  case eten: GaEten(); break;
  case slapen: GaSlapen(); break;
}


Patterns zijn leuk, maar niet heiligmakend ;) We praten hier niet over business logica, bedrijfsprocessen aan de hand van hun toestanden in een bepaalde execution volgorde afhandelen ;)

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
paulgielens schreef op 23 oktober 2002 @ 16:56:
ikke onder vuur ;)


[...]
Nou zo slecht is dit ook weer niet.

code:
1
2
3
4
5
switch (mijn_state)
{
  case eten: GaEten(); break;
  case slapen: GaSlapen(); break;
}
Zie het boek : 'Refactoring : Improving the design of existing code'
pag 255: Replace Conditional with Polymorphism :)

Het voordeel aan mijn code is dat je kleine brokken met herbruikbare code hebt. En bij jou is het gewoon 1 klont code.
Patterns zijn leuk, maar niet heiligmakend ;)
Mijn code heeft een aantal voordelen. Jouw code is 'simpeler' qua class hierarchie maar die van mij is beter te reusen en in mijn ogen ook vele male inzichtelijker. Ik heb al heel wat slechte code geschreven en monolythen is vaak een oorzaak van enorm veel problemen. Ik probeer ze dus echt te verkomen. En verder vind ik een goed ontworpen systeem ook erg belangrijk omdat je er erg veel profijt van kan hebben.
We praten hier niet over business logica, bedrijfsprocessen aan de hand van hun toestanden in een bepaalde execution volgorde afhandelen ;)
Deze snap ik niet.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Geen matches
Zie MSDN Magazine 2 state design pattern :)

Ja de hierboven geposte code is inderdaad beter herbruikbaar

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
paulgielens schreef op 23 oktober 2002 @ 17:19:
Zie MSDN Magazine 2 state design pattern :)
Ik heb het GoF boek al en whoami heeft hem ook net binnen :)

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Ik heb al een deel v/d logger geimplementeerd, en deze ziet er dan als volgt uit:

Interface ILogWriter
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface ILogWriter
{
  void SetupLogger  ( string logto );
  void StartLogging ();
  void WriteLog     ( LogEntryType  entryType,
                      string        userId,
                  string        module,
                  string        errorCode,
                  string        message );
  void WriteLog     ( LogEntryType  entryType,
                      string        userId,                         
                 Exception     errorException );
  void  EndLogging   ();
}


De LogWriter classes implementeren deze interface en zorgen er dus voor dat de error of de
gebeurtenis op de juiste manier naar het betreffende medium wordt weggeschreven.

De Logger class zelf ziet er als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Logger
{
  private ILogWriter     m_LogWriter;
  private LogSourceType  m_LogType;
  private string         m_LogTo;

  private void CheckLogger ( LogSourceType sourceType )
  {
     // In deze method ga ik gaan kijken welke ILogWriter
     // momenteel de actieve is.  Is sourceType == m_LogType,
     // dan moet er niets gebeuren.  Indien er 
     // wel naar een ander medium moet gelogged worden,
     // dan roep ik de ILogWriter.EndLogging aan en maak
     // ik een nieuwe LogWriter (afhankelijk van het gespecifieerde type.
     // Daarvan roep ik dan de SetupLogWriter en de StartLogging aan.
  }

  public void WriteLog (....)
  {
    this.CheckLogger (sourceType);
    m_LogWriter.WriteLog (...)
  }
}

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik vind dit wel een beetje onhandig overkomen. Het kan toch voorkomen dat je naast elkaar meerdere logobjecten hebt omdat je meerdere logtypes hebt. Nu loop je iedere keer onnodig als die ojbecten te sluiten en te openen. En hoe ga je verder een crashende db log oplossen? (Dat was een voorwaarde van je).

Heb je nog even gekeken naar mijn laatste oplossing?

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
En als je verder de juiste methode selectie zou willen hebben op basis van een logtype, is dat ook totaal geen probleem. Je zou dan gewoon daarover kunnen dispatchen (eventueel met een switch-case/if else reeks *yuk* of met een visitor 8-) (of je kan ook een echte taal nemen) :P )

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 12:37:
Ik vind dit wel een beetje onhandig overkomen. Het kan toch voorkomen dat je naast elkaar meerdere logobjecten hebt omdat je meerdere logtypes hebt. Nu loop je iedere keer onnodig als die ojbecten te sluiten en te openen.
Hmm, ja.... is wel waar.
En hoe ga je verder een crashende db log oplossen? (Dat was een voorwaarde van je).
Dit moet ik nog doen.
Heb je nog even gekeken naar mijn laatste oplossing?

[/quote]
Yep. Daar heb je idd een object voor iedere ILogWriter in je logclass. Zou ik eigenlijk ook kunnen doen.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 12:47:
En als je verder de juiste methode selectie zou willen hebben op basis van een logtype, is dat ook totaal geen probleem. Je zou dan gewoon daarover kunnen dispatchen (eventueel met een switch-case/if else reeks *yuk* of met een visitor 8-)
Momenteel doe ik het met een switch, en da's idd wel yuk. Dat visitor pattern moet ik nog bekijken.
(of je kan ook een echte taal nemen) :P )

Hoezo?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 25 oktober 2002 @ 13:02:
[nohtml]
Momenteel doe ik het met een switch, en da's idd wel yuk. Dat visitor pattern moet ik nog bekijken.
Maak hem eerst maar met die switch, dan help ik je later wel om hem om te bouwen naar een visitor. Is niet zo lastig :)
Hoezo?
Nice :P

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
Ok, ik heb het ontwerp nog eens aangepast. :P

Nu ziet het er als volgt uit:
Afbeeldingslocatie: http://users.pandora.be/fgzone/schema4.jpg

Ik heb dus geen interface meer. Ik heb er een abstracte class van gemaakt, omdat ik naast functies ook nog de status van de logger wil bijhouden. (Gestart of niet).

In m'n logger class maak ik dus voor iedere concrete LogWriter een instantie. Ik hou ook een variable bij van het type LogWriter.

In m'n method WriteLog, roep ik de functie PrepareLogger aan. Deze gaat op zijn beurt de SelectLogger en de GetLogTo members aanroepen. De SelectLogger zorgt ervoor dat de juiste concrete LogWriter aan Logger wordt toegekend, zodat ik vanaf dan iedere keer naar Logger kan referen voor het aanroepen van de member functies. GetLogTo gaat in een xml-file gaan kijken wat de connectie-string is voor de databank of hoe de logfile moet noemen...
PrepareLogger zorgt er ook voor dat de LogWriter.StartLogger method aangeroepen wordt mocht dat nodig zijn.

Owja, thx voor de input/hulp tot dusver Alarmnummer. :)
Wel beetje jammer dat er blijkbaar niet veel anderen geinteresseerd zijn in designen. :P

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
Ik vind die logger class nog steeds vrij horkerig als ik eerlijk ben. En ik snap dat je een abstract class wilt gebruiken, maar het is echt een stuk handiger om toch eerst een interface ervoor te plakken. Je laat dan die abstracte class die interface implementeren, en verder kan iedere implementatie die abstracte class implementeren, of die interface. Hierdoor kan je code sharen, maar toch hou je vrijheid. Abstracte classes worden veel te vaak verkeerd gebruikt en mensen die hangen er veel te veel ontwerp waarde aan. Kijk maar eens naar de opzet van het Collectionframe work van java of .NET. Je zult zien dat ze overal een interface voorop zetten, en abstracte classes zijn alleen nuttig voor gemeenschappelijke implementaties, verder niet.

En verder zou ik die constructors van die writers gewoon goed maken. Je geeft ze allemaal een string mee waar ze al hun info uit moeten vissen en daar kan je gewoon fouten mee maken. Ik zou dus gewoon goeie constructors aanmaken, en dan de gemaakte writers aan de logger toevoegen. Hierdoor hoef je dat niet te doen via zo`n vieze string.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 14:33:
Ik vind die logger class nog steeds vrij horkerig als ik eerlijk ben.
Hmm.... Wat vind je er dan niet goed aan?
En verder zou ik die constructors van die writers gewoon goed maken. Je geeft ze allemaal een string mee waar ze al hun info uit moeten vissen en daar kan je gewoon fouten mee maken. Ik zou dus gewoon goeie constructors aanmaken, en dan de gemaakte writers aan de logger toevoegen. Hierdoor hoef je dat niet te doen via zo`n vieze string.

Je doelt op die SetupLogger method? Die krijgen een string mee, maar daar staat niet zoveel info in hoor. In het geval van een textfilelogwriter gaat dat de bestandsnaam zijn van de file waarnaar moet gelogged worden, in het geval van een DbLogWriter is het de connectionstring.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 25 oktober 2002 @ 14:37:
Hmm.... Wat vind je er dan niet goed aan?
Ik zal hier even over prakkadenken :)
Je doelt op die SetupLogger method? Die krijgen een string mee, maar daar staat niet zoveel info in hoor. In het geval van een textfilelogwriter gaat dat de bestandsnaam zijn van de file waarnaar moet gelogged worden, in het geval van een DbLogWriter is het de connectionstring.
Maar waarom is die gemeenschappelijke 'constructor' methode nodig? Waarom kan je niet bij het aanmaken van die logger meteen even de aangemaakte writers even in de constructor meegeven? Ik neem aan dat we het beiden er wel over eens zijn dat non string date in een string te stoppen niet echt netjes is :) Verder weet je niet wat voor argumenten die andere writers mee moeten krijgen (vooral met het oog op de toekomst) en ik zie dus niet in waarom je je zo wilt beperken. Ik vermoed dat je graag wilt dat het allemaal eenvormig is?
Owja, thx voor de input/hulp tot dusver Alarmnummer.
Ik ben blij dat er weer eens een leuk onderwerp langskomt.
Wel beetje jammer dat er blijkbaar niet veel anderen geinteresseerd zijn in designen.
Nogal ja. Niemand die met andere ideeen komt aanzetten.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 14:55:

Ik neem aan dat we het beiden er wel over eens zijn dat non string date in een string te stoppen niet echt netjes is :)
Idd, dat doe ik dan dus ook niet. ;) Yekkes.
Maar waarom is die gemeenschappelijke 'constructor' methode nodig? Waarom kan je niet bij het aanmaken van die logger meteen even de aangemaakte writers even in de constructor meegeven?
Verder weet je niet wat voor argumenten die andere writers mee moeten krijgen (vooral met het oog op de toekomst) en ik zie dus niet in waarom je je zo wilt beperken. Ik vermoed dat je graag wilt dat het allemaal eenvormig is?

Ik zal er ook eens over nadenken.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 25 oktober 2002 @ 14:57:
Ik zal er ook eens over nadenken.
Het probleem is denk ik dat jij c++ gewent bent, en daar is het wel mogelijk om van meerdere objecten over te erven. In java wil dat gewoon niet, en daarom zorg ik er nu voor dat ik altijd begin vanuit een interface. Ten 1e kan ik van zoveel objecten overerven als ik maar wil (makkelijk voor polymorphisme) en daarnaast vind ik het ook enorrm duidelijk. Als een object via een interface wordt aangesproken, kan ik beter zien via welke methodes de communicatie verloopt.

En als laatste kan je gewoon makkelijker ontwerpen. Je zet de interfaces op en die implementatie die kan nog wel een tijdje blijven liggen omdat je weet dat iedere implementatie aan die intertface moet voldoen.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
Alarmnummer schreef op 25 oktober 2002 @ 15:03:
[...]

Het probleem is denk ik dat jij c++ gewent bent, en daar is het wel mogelijk om van meerdere objecten over te erven. In java wil dat gewoon niet, en daarom zorg ik er nu voor dat ik altijd begin vanuit een interface. Ten 1e kan ik van zoveel objecten overerven als ik maar wil (makkelijk voor polymorphisme) en daarnaast vind ik het ook enorrm duidelijk.
Tja, dat je dan meerdere interfaces aan een class kunt koppelen ok, maar in dit geval zal dat niet nodig zijn. Ik kan natuurlijk nog altijd een base-class maken en een interface. Maar dit was nu gewoon ff de snelste oplossing.
Als een object via een interface wordt aangesproken, kan ik beter zien via welke methodes de communicatie verloopt.
Hier zie ik het verschil tsn duidelijkheid tsn interface en abstract class niet in hoor.
En als laatste kan je gewoon makkelijker ontwerpen. Je zet de interfaces op en die implementatie die kan nog wel een tijdje blijven liggen omdat je weet dat iedere implementatie aan die intertface moet voldoen.

Als je overerft van een abstract class (met abstracte functies dus), dan weet je dat ook zeker. Alle abstracte methods moet je overriden, anders krijg je compiler-errors.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Geen matches
whoami schreef op 22 oktober 2002 @ 15:43:
[...]
Ik heb die log4j eens gedowned maar nog niet bekeken. Thx anyway.
[...]
Wat bedoel je hier precies? Ik heb in m'n errorlogger geen db-connectie of bestand. Deze zitten in de classes DatabaseLogWriter en FileLogWriter.
Zelf gebruik ik Log4J vrij veel en vind het een erg goede implementatie van de functionaliteit die je mag verwachten voor wat betreft logging. Uiteraard gaat het veel te ver om al die functionaliteit 'even' opnieuw te implementeren, maar een aantal concepten zijn denk ik wel erg handig.

Log4J werkt met een hierarchy van Categories. Een Category is datgene waar je applicatie naar toe schrijft met statements als mijnCategory.error("Hopeloos", error); In jouw geval heb je eigenlijk maar een Category, je ErrorLogger.

Aan zo'n Category worden 1 of meer Appenders gehangen, deze zijn vergelijkbaar met jouw LogWriters. Het centrale punt blijft dat je de logging zo los mogelijk wilt hebben van de applicatie. De applicatie moet alleen aangeven dat hij wil loggen (door een instantie van je ErrorLogger aan te maken) en vervolgens worden er log acties gedaan door middel van logger.log("log dit!"). Je kunt een aantal log levels definieren en de applicatie door middel van het aanroepen van de juiste methode (logger.log(), logger.error(), logger.fatal(), logger.info()...) aan laten geven wat het loglevel van een bepaalde message moet zijn.

Op die manier ben je ook in staat om zonder de code aan te passen, doordat je voor een bepaald loglevel een andere LogWriter configureert.

Iets wat ik niet goed snap zijn die LogSourceTypes. Ten eerste vind ik de naam verwarrend omdat het eigenlijk LogTargetTypes zijn en ten tweede is het 3 keer een manier van opslaan (db, file, event log) en 1 keer een formattering (XML). Ik zou dat uit elkaar trekken en een 4e manier van opslaan er bij doen: console.

With the light in our eyes, it's hard to see.


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Matched: abstract
whoami schreef op 25 oktober 2002 @ 15:09:
[nohtml]
[...]
Tja, dat je dan meerdere interfaces aan een class kunt koppelen ok, maar in dit geval zal dat niet nodig zijn. Ik kan natuurlijk nog altijd een base-class maken en een interface. Maar dit was nu gewoon ff de snelste oplossing
En dat is een argument om je ontwerp maar te laten verloederen ;)
Hier zie ik het verschil tsn duidelijkheid tsn interface en abstract class niet in hoor.
Omdat je de interface alleen methodes declareerd, en geen hulpmethodes ed. En verder is het verschil tussen een interface en abstract class dat je van tig interfaces kan overerven, maar van maar 1 abstracte class. (maar dat wist je al :P)
Als je overerft van een abstract class (met abstracte functies dus), dan weet je dat ook zeker. Alle abstracte methods moet je overriden, anders krijg je compiler-errors.
Maar bij een abstracte class begin je al wel vaak aan gemeenschappelijke methodes. Als een abstracte class alleen maar abstracte methodes heeft, dan had je het sowieso beter een interface kunnen maken. Als niet alles abstract is, dan loop je al weer te implementeren. En vaak is het beter om dat uit te stellen. Verder vind ik interfaces ook veel overzichtelijker dan classes omdat je die implementaties niet hoeft zien.

Ik heb vroeger ook alles ontworpen van abstracte classes, maar interfaces zijn echt vele malen handiger (en krachtiger).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Bobco schreef op 25 oktober 2002 @ 15:11:
[...]

Iets wat ik niet goed snap zijn die LogSourceTypes. Ten eerste vind ik de naam verwarrend omdat het eigenlijk LogTargetTypes zijn en ten tweede is het 3 keer een manier van opslaan (db, file, event log) en 1 keer een formattering (XML). Ik zou dat uit elkaar trekken en een 4e manier van opslaan er bij doen: console.


:+
Daar heb je wel zeker een punt. Ik heb een tijdje zitten denken op een goede naam en ik vond eigenlijk ook wel dat source niet zo goed was.... Natuurlijk nooit op Target gepeisd.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Geen matches
whoami schreef op 25 oktober 2002 @ 15:15:
Daar heb je wel zeker een punt. Ik heb een tijdje zitten denken op een goede naam en ik vond eigenlijk ook wel dat source niet zo goed was.... Natuurlijk nooit op Target gepeisd.
Ik zou ook nog maar eens heel goed nadenken over hoe configureerbaar je het allemaal wilt hebben. Mijn verhaaltje over Log4J is een beetje wazig, je moet echt kijken naar de User Manual van Log4J. Daar staat een helder en begrijpelijk verhaal in over Categories, Appenders, layouts en al die andere zaken.

Mijn eigen voorkeur gaat altijd uit naar applicaties waarvan het gedrag gemakkelijk te wijzigen is als je dat wilt. Code-aanpassingen zijn dan uit den boze.

Nu lijkt je ontwerp een beetje aan te sturen op een vaste set van LogWriters die er blijkbaar altijd moeten zijn. Dat wordt lastig als er bijvoorbeeld geen database is, of wanneer je (ik ben Java gewend, vandaar) op een systeem opeens geen NT Event Log blijkt te hebben omdat je op Linux draait.

Daarom vind ik het uitgangspunt van Log4J dat de applicatie aangeeft in welke categorie (en dat is een functioneel begrip) er moet worden gelogd, waarna de configuratie bepaald waar die logging uiteindelijk terecht komt, ook heel goed. Je applicatie hoeft zich in de code dan niet meer bezig te houden met de omgeving waarin gedraaid wordt omdat dat allemaal in de configuratie gebeurd.

With the light in our eyes, it's hard to see.


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
[nohtml]
Bobco schreef op 25 oktober 2002 @ 15:48:
[...]

Nu lijkt je ontwerp een beetje aan te sturen op een vaste set van LogWriters die er blijkbaar altijd moeten zijn. Dat wordt lastig als er bijvoorbeeld geen database is, of wanneer je (ik ben Java gewend, vandaar) op een systeem opeens geen NT Event Log blijkt te hebben omdat je op Linux draait.
Idd, je hebt wel een punt hier.
Er wordt idd zowiezo een TextLogWriter, DbLogWriter, .... object gemaakt in m'n Logger class. Maar, zolang er in de applicatie nooit een aanvraag gedaan wordt om naar de db te loggen, dan gaat er ook geen connectie gemaakt worden naar die db. Het is ook de bedoeling dat, als er geen db aanwezig is en er toch naar de db moet gelogged worden, er dan automatisch naar een textfile of xml-file gelogged wordt. Dit zou ik eigenlijk bij alle LogWriters kunnen implementeren. (Dus ook bij de eventlogger).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
whoami schreef op 25 oktober 2002 @ 15:52:
[nohtml]
[...]

Idd, je hebt wel een punt hier.
Er wordt idd zowiezo een TextLogWriter, DbLogWriter, .... object gemaakt in m'n Logger class. Maar, zolang er in de applicatie nooit een aanvraag gedaan wordt om naar de db te loggen, dan gaat er ook geen connectie gemaakt worden naar die db. Het is ook de bedoeling dat, als er geen db aanwezig is en er toch naar de db moet gelogged worden, er dan automatisch naar een textfile of xml-file gelogged wordt. Dit zou ik eigenlijk bij alle LogWriters kunnen implementeren. (Dus ook bij de eventlogger).
Maar je Logger die is juist zo onflexibel (je komt bv in de problemen als je om een of andere reden naar meer files wilt schrijven) Daarom heb ik ook een specifieke logger gemaakt, die niets anders is dan een houder van een aantal door jouw opgegeven log'stromen'

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 16:02:
[...]

Maar je Logger die is juist zo onflexibel (je komt bv in de problemen als je om een of andere reden naar meer files wilt schrijven) Daarom heb ik ook een specifieke logger gemaakt, die niets anders is dan een houder van een aantal door jouw opgegeven log'stromen'


Mwoah. Laat het ons erop houden dat er per LogWriter maar 1 logstroom is. :+

* whoami geeft er de brui aan voor vandaag (en voor deze week). :P

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Matched: abstract
Design ziet er solide uit alleen ga ik mee in het interface verhaal. LogWriter is zeker een abstractie dus dat moet je mooi zo laten! Alleen?!? probleem is dat je methodes nagenoeg altijd een andere implementatie heeft...wellicht dat interfaces toch mooier is. Overriding levert wel de nodige overhead op, maar ik zie zo vlug geen andere uitweg.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Matched: abstract
paulgielens schreef op 25 oktober 2002 @ 16:24:
Design ziet er solide uit alleen ga ik mee in het interface verhaal. LogWriter is zeker een abstractie dus dat moet je mooi zo laten! Alleen?!? probleem is dat je methodes nagenoeg altijd een andere implementatie heeft...wellicht dat interfaces toch mooier is. Overriding levert wel de nodige overhead op, maar ik zie zo vlug geen andere uitweg.
Een interface is idd wel mooier, maar ik heb die abstract class gekozen omdat er een attribuut is die iedere LogWriter nodig heeft, nl. Started.
In de StartLogging method van Logwriter zet ik die op True en in de EndLogging op false. Die 2 methods en dat attribuut kan ik dus zeker niet in de interface kwijt.

Ik kan dan wel de andere methods in een interface steken, maar dan zie ik er eigenlijk niet zo veel nut van in om ze in een interface te steken ipv ze abstract te laten in de LogWriter class.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Matched: abstract
Uhm started kan gewoon in de interface opgenomen worden, zodat deze in de implementatie meegenomen dient te worden.

En ja ik ben het met je eens dat het abstractie is, maar gezien de uitwerking twijfel ik of interfacing niet de enige juiste manier is.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Ik ben niet thuis en heb op de terugweg eens zitten denken (jah, tijd genoeg gehad 1u30 onderweg geweest).

Stel dat m'n Logger class er als volgt uit ziet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Logger
{
   private TextFileLogwriter txtlw;
   private DbLogWriter        dblw;
  
   private static Logger       logger;

   private void PrepareLogger();
   private void CheckLogger();

   public static WriteLog()
   {
      logger.PrepareLogger();
      logger.CheckLogger();
   }
}


maw, kan ik gewone member methods aanroepen op een static attribute ?
* whoami hoopt dat hij een beetje duidelijk is.
* whoami kan het hier niet uittesten.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Waar wil je die Logger aanmaken? Op deze manier krijg je een nullpointer exception.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Owja, vergeten natuurlijk omdat het vanzelfspreken is...

Het Logger object (dat static is), wordt in een static constructor aangemaakt. Dat is te enige plaats waar je in .NET static members kunt creeëren.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Jij hebt er een soort singleton object van gemaakt. Ik zou het Singleton design pattern even bekijken. En verder kan je niet meer bij je velden komen. Niet bij je statische velden, en niet bij de velden van de Logger .

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 19:53:
Jij hebt er een soort singleton object van gemaakt. Ik zou het Singleton design pattern even bekijken. En verder kan je niet meer bij je velden komen. Niet bij je statische velden, en niet bij de velden van de Logger .


Ga ik proberen van te doen dit weekend. ;)

Hoe bedoel je, je kan niet meer bij de velden komen?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Ik zie geen getters staan, en alle velden zijn private :) Dus als je bij die logger class een instance hebt gemaakt, dan kan je niet meer bij die instance komen. En als je er wel bij kon komen, dan kon je weer niet bij de velden van die instance komen. Daarnaast krijg je ook geen foutmelding als je meerdere keren die statische methode aanroept. Dit heeft als gevolg dat er een nieuw logger object wordt aangemaakt (denk ik bij jou) en het oude logger object die is weg.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 19:59:
Ik zie geen getters staan, en alle velden zijn private :) Dus als je bij die logger class een instance hebt gemaakt, dan kan je niet meer bij die instance komen. En als je er wel bij kon komen, dan kon je weer niet bij de velden van die instance komen. Daarnaast krijg je ook geen foutmelding als je meerdere keren die statische methode aanroept. Dit heeft als gevolg dat er een nieuw logger object wordt aangemaakt (denk ik bij jou) en het oude logger object die is weg.


Ja, dat weet ik wel...... :P
Ik heb er gewoon geen properties of getters/setters bij gezet om niet te veel te moeten typen. Zoiets elementairs wist ik wel hoor. :P

Dat van die foutmelding en ervoor zorgen dat het oude niet overschreven wordt, daar moet ik idd nog voor kijken. Maargoed, da's voor maandag. Eerst weekend. ;)

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Geen matches
Tijdje geen T.net gechecked, en bijna deze gemist :o
Interessante design-discussie. Die soms overigens over nogal taalspecifieke zaken gaat, maar goed...

grappig ook om te zien dat alarmnummers versie vrijwel gelijk is aan wat ik tegenwoordig gebruik (al is dat bij mij dan in C++, en kunnen er meerdere 'logstromen' in de 'logger', die bij mij 'logprovider' heet...)

Whoami : ik zou je willen aanraden je logsysteem zo flexibel mogelijk op te lossen. Dit omdat verschillende soorten applicaties nogal eens verschillende eisen aan de logging stellen (niet alleen waarnaar gelogt moet worden, maar ook wat, welk formaat, waarvandaan, en wanneer).

Het lijkt me overigens dat je er al wel redelijk uitbent. Ik weet ook niet waarvoor je het precies maakt, en of je dit in de toekomst overal in gaat gebruiken. Is het eenmalig voor een projectje, dan kan de tradeoff slechter design<>sneller gebouwd nog wel eens de moeite waard zijn (ik weet het, dat is hier natuurlijk als vloeken in de kerk ;) ). Uiteindelijk is er niet zoiets als het 'perfecte design', o.a. door voortschrijdend inzicht kan je uiteindelijk wel tot in het oneindige blijven aanpassen, je moet ook een keer tevreden kunnen zijn met het resultaat, zelfs als je denkt dat het misschien nog wel beter kan....

Acties:
  • 0 Henk 'm!

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

Alarmnummer

-= Tja =-

Geen matches
Verwijderd schreef op 25 oktober 2002 @ 20:32:
Tijdje geen T.net gechecked, en bijna deze gemist :o
Interessante design-discussie. Die soms overigens over nogal taalspecifieke zaken gaat, maar goed...
het gaat over het oo paradigma in het algemeen, maar ik ben er eerlijk gezegd niet veel taal specifieke code in tegen gekomen.
Whoami : ik zou je willen aanraden je logsysteem zo flexibel mogelijk op te lossen. Dit omdat verschillende soorten applicaties nogal eens verschillende eisen aan de logging stellen (niet alleen waarnaar gelogt moet worden, maar ook wat, welk formaat, waarvandaan, en wanneer).
Ik sluit me hier volledig bij aan. Daarom heb ik ook die specifieke logger class gemaakt, daar kan je dan de logstromen die je hebt in plaatsen. En verder kan je gebruik maken van hele reusable componenten, dus je hoeft alleen dat specifieke log object in elkaar te zetten.
Het lijkt me overigens dat je er al wel redelijk uitbent. Ik weet ook niet waarvoor je het precies maakt, en of je dit in de toekomst overal in gaat gebruiken. Is het eenmalig voor een projectje, dan kan de tradeoff slechter design<>sneller gebouwd nog wel eens de moeite waard zijn (ik weet het, dat is hier natuurlijk als vloeken in de kerk ;) ). Uiteindelijk is er niet zoiets als het 'perfecte design', o.a. door voortschrijdend inzicht kan je uiteindelijk wel tot in het oneindige blijven aanpassen, je moet ook een keer tevreden kunnen zijn met het resultaat, zelfs als je denkt dat het misschien nog wel beter kan....
We zitten hier op GoT, we designen alles perfect ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Matched: abstract
het gaat over het oo paradigma in het algemeen, maar ik ben er eerlijk gezegd niet veel taal specifieke code in tegen gekomen.
In C++ gaat multiple inheritance van abstract classes anders prima... Hele interface bestaat daar niet (niet als keyword iig). Tenzij je hier interface als in het OO paradigma bedoeld, wat zich voor C++ vertaalt naar een abstract class zonder enige implementatie. Dat bedoelde ik dus met taalspecifiek.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Alarmnummer schreef op 25 oktober 2002 @ 19:59:
Ik zie geen getters staan, en alle velden zijn private :) Dus als je bij die logger class een instance hebt gemaakt, dan kan je niet meer bij die instance komen.


Als je een instance van een class maakt binnen de class, dan kan die instance wel aan de private fields komen hoor.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Test
{
  private int   _getal;
  private static Test _test;

  static Test()
  {
     _test = new Test();
  }

  public static int getGetal()
  {
     return _test._getal;
  }

}


Bovenstaande code zou perfect moeten werken.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • tomato
  • Registratie: November 1999
  • Niet online
Geen matches
whoami schreef op 28 oktober 2002 @ 13:36:
Als je een instance van een class maakt binnen de class, dan kan die instance wel aan de private fields komen hoor.
Volgens mij kun je zelfs bij de private velden wanneer je een instance van een derived class maakt (mits de velden in de base class voor komen natuurlijk).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:17
Geen matches
Ok. Even een update.
Ik heb die logger voor het grootste deel geimplementeerd. Het design ziet er als volgt uit:

Afbeeldingslocatie: http://users.pandora.be/fgzone/schema5.jpg

Er zijn wel nog enkele dingen die ik niet zo goed vind en waar ik nog een oplossing moet voor zoeken, zoals die static EndLogging method in de class Logger. (Zie ook dit topic: [rml][ C#] Destructors en garbage collection[/rml]).

Als er gelogged wordt naar de databank en de databank is om een of andere reden offline, wordt er automatisch naar een ander type gelogged (een xml-file bv). Dit doe ik door in het catch blok waar ik de databank exception afvang de static method WriteLog aan te roepen, maar dan met een andere parameter.

https://fgheysels.github.io/

Pagina: 1