DMA Design Project - first submission
m |
m |
||
Line 54: | Line 54: | ||
* It also makes sense to be able to log items in a XML format, which means creating a new logger to log items as XML. | * It also makes sense to be able to log items in a XML format, which means creating a new logger to log items as XML. | ||
* During implementation testing in C# in .Net 4.0 it was discovered | * During implementation testing in C# in .Net 4.0 it was discovered | ||
− | If there is a class A, which contained a method M and a second class B, that was a subclass of A that overrode method M, then whenever an instance of class B was passed through to any method as type A, calling M on the instance of B did not invoke the overridden M on B but actually called the M on the base class A. | + | :''If there is a class A, which contained a method M and a second class B, that was a subclass of A that overrode method M, then whenever an instance of class B was passed through to any method as type A, calling M on the instance of B did not invoke the overridden M on B but actually called the M on the base class A.'' |
− | This appeared to be part of a conspiracy to encourage the use of interfaces in .Net by Microsoft. So to fit in better with other designs it was changed to make more use of interfaces. In particular the file, rolling file and split file logger classes were changed to implement a new file logger interface to ensure that the correct method was called on the correct class. | + | :This appeared to be part of a conspiracy to encourage the use of interfaces in .Net by Microsoft. So to fit in better with other designs it was changed to make more use of interfaces. In particular the file, rolling file and split file logger classes were changed to implement a new file logger interface to ensure that the correct method was called on the correct class. |
* Under some circumstances it would be necessary to receive notifications when items were logged. Initially this was implemented in the form of a decorator class that added observable functionality to any logger class. However if this decorator class was wrapped around a logger class that extended the interface of the Logger class, such as the memory logger, then the extra functionality was no longer available. So the design was changed to add observable functionality only to the memory logger class as that seemed the most logical place it would be required. | * Under some circumstances it would be necessary to receive notifications when items were logged. Initially this was implemented in the form of a decorator class that added observable functionality to any logger class. However if this decorator class was wrapped around a logger class that extended the interface of the Logger class, such as the memory logger, then the extra functionality was no longer available. So the design was changed to add observable functionality only to the memory logger class as that seemed the most logical place it would be required. | ||
Revision as of 23:49, 28 July 2010
Contents |
Cosc427 Design Project 2010 - Darryl Anderson
In the beginning
In the beginning there was an idea, and like most good ideas it was simple.
A logging system capable of logging any sort of data (as long as it was plain text) and to any destination.
New and improved
But like all ideas it grew and expanded until it needed to:
- Log items to any type of destination, including but not limited to, the Windows event log, a file, the debug or console window inside the Visual Studio IDE or memory.
- Filter what items are logged but with a filter that can be changed on the fly.
- Specify how each item is formatted before output.
- Log to multiple destinations using a single logger.
- ‘Roll over’ a log file based on date or file size or any other specified criteria.
- Allow the severity for each log entry to be specified.
- Assign each item logged a category.
- Log items to a XML file in an efficient manner.
- Log any types of items, as long as it is a string or maybe an exception.
And behold it was good.
In the making
There was much deep thought and gnashing of teeth in the above design which resulted in:
- It can only log strings, why would you need anything else.
- The loggers included in the design cover all known logging requirements, though it is possible, however unlikely, that others may be needed.
- The SplitFileLogger or RollingFileLogger classes have been cleverly designed using the decorator design pattern to allow a file logger to be wrapped many times.
- The rolling file logger cried out for the strategy design pattern for the roll over algorithm and so it was.
- Formatter classes are not responsible for the formatting of the entry text.
- In order to save tedious coding when creating new logger classes the Logger class is an abstract class that contains all the common functionality between the different loggers, including helper functions around the filtering and formatting of items. This makes it much simpler to define new loggers and obeys the ‘Programming by difference’ and ‘Encapsulate that which varies’ principles.
- The filter, formatting and rollover strategy classes are interfaces because the implementations between the different types for each can widely differ.
Just so you will know
This framework is part of a project to be written using C#, in .Net 4.0 and has a secondary goal of exploring the use of code contracts, prompted in part by the new inbuilt support for code contracts in .Net 4.0
Properties in the design will be shown with separate getters and setters. This is so that it can be easily seen which properties are read only, set only or have different access modifiers. However properties will be implemented using the inbuilt property mechanism in C# where the getter and setters for a property have a single name. This violates the Riel's heuristic ‘Command query separation’ but I believe it is acceptable because it follows the standard programming practices for .Net and it is obvious what code is calling the ‘getter’ and what is calling the ‘setter’.
The name of interfaces will have an ‘I’ prefix which again follows the standard programming practices for.Net in general.
Greatest ever
Despite being the greatest piece of software design known to humankind there were some issues. Not many but some. A few were due to the design itself and the rest were due to the language the design was implemented using, i.e. C#.
- It turned out just logging plain text did not cut the mustard. Other data types need also to be logged, including exceptions. Changing the design to employ generics allowed different data types to be logged without having to create logger classes for each different type. This does mean however that a formatter class is needed per data type logged.
- It also makes sense to be able to log items in a XML format, which means creating a new logger to log items as XML.
- During implementation testing in C# in .Net 4.0 it was discovered
- If there is a class A, which contained a method M and a second class B, that was a subclass of A that overrode method M, then whenever an instance of class B was passed through to any method as type A, calling M on the instance of B did not invoke the overridden M on B but actually called the M on the base class A.
- This appeared to be part of a conspiracy to encourage the use of interfaces in .Net by Microsoft. So to fit in better with other designs it was changed to make more use of interfaces. In particular the file, rolling file and split file logger classes were changed to implement a new file logger interface to ensure that the correct method was called on the correct class.
- Under some circumstances it would be necessary to receive notifications when items were logged. Initially this was implemented in the form of a decorator class that added observable functionality to any logger class. However if this decorator class was wrapped around a logger class that extended the interface of the Logger class, such as the memory logger, then the extra functionality was no longer available. So the design was changed to add observable functionality only to the memory logger class as that seemed the most logical place it would be required.
Perfection
And thus perfection was at last achieved.
Just between you and me
A lot of changes that appear in the revised design are due to issues and complications found during a test implementation of the initial design, in particular the changes made around the file logger class and its subclasses. The changes made to the file logger do work and are effective but they seem wrong, very wrong. Smell bad even. It appears that some of issues with the design stem from the fact that C# uses class encapsulation and not object encapsulation and that desire on my part to reduce the amount of duplicated code by using abstract and derived classes. One example is the file logger class and its subclasses. The file logger class has code to write items logged to a file and so the split file logger and rolling file logger classes extend the file logger class to make use of this code. If those two classes did not extend the file logger class but just implemented the file logger interface then the design would be cleaner but most likely result in duplicated code.
On the surface it seemed that the XML logger is just a subtype of a split file logger as the XML logger will create two files. It was designed to allow efficient logging of items in a XML format but creating a header file that was a complete XML document that contained an entity pointing to the data file. This allows items to be logged to the data file by simply appending new items at the end. It does however smack a bit of ‘inheritance for implementation’ as the XML logger should not expose the full interface of the split file logger. A better solution may be for the XML logger class to contain an instance of a split file logger.
Finally
The design above does not show all the classes that are expected to be included in the framework. In particular there will be a collection of formatter classes for some common data types including strings and exceptions.