Re: MVP's: static methods in interfaces. (REDEFINED)
From: Nick Malik [Microsoft] (nickmalik_at_hotmail.nospam.com)
Date: 12/22/04
- Next message: CK: "Re: Threading question"
- Previous message: CK: "Threading question"
- In reply to: Dan Bass: "Re: MVP's: static methods in interfaces. (REDEFINED)"
- Messages sorted by: [ date ] [ thread ]
Date: Wed, 22 Dec 2004 08:28:45 GMT
Hello Dan,
> How would you approach the following:
>
> In developing an application, it becomes obvious that a few lines of code
is
> being repeated more than a few times and so refactoring is to be done. The
> thing is it's not necessarily object specific, but more of a general set
of
> commands.
I would start with the question: what is similar between each case, and what
varies. The things that are similar should be pushed toward the top of the
inheritance tree, while the things that vary should be encapsulated. (This
is a short-hand definition of "commonality variability analysis" or CVA.
Refer to [Coplien] and [Shalloway]).
On the surface, if there is a set of repeating statements within a set of
related classes, I would think "strategy pattern" and that's where the
paragraph above led me... until I read the next part...
> This is referenced all over applications, across different projects in my
> solution (which means it's in a constants / enum definitions / type class
> library) every time an exception of any sort is thrown for logging
purposes.
well... the strategy pattern appears to go right out the window. After all,
the repeating code is not part of related classes! So I start to think
about what you are trying to accomplish.
You defined a static method (some would call it a "helper" method) that
takes an exception object and returns a string suitable for throwing to a
log file or an exception handler of some kind.
Clearly, the thing that varies is this: what will we do with this string?
The thing that is constant is: we need a uniform description of the
exception that contains an inordinately large amount of information. :-)
So, the creation of this string is at the top, perhaps as a concrete method
in an abstract class. The classes that inherit from that abstract class
will use this method by the fact that it is defined in the base class. The
inherited members will decide how to log the error.
So, it would look something like this:
// caveat: air code. I didn't compile this. Please forgive typos.
public abstract class IExceptionClass
{
private string ExceptionInfo ( Exception ex )
{
if ( ex == null ) return "";
StringBuilder sb = new StringBuilder();
sb.Append( " Exception: " );
sb.Append( ex.Message );
sb.Append("\r\n");
sb.Append( " Stack Trace: ");
sb.Append( ex.StackTrace );
return sb.ToString();
}
public void LogThisEvent(Exception ex)
{
string DisplayString = ExceptionInfo(ex);
WriteEventToLog(DisplayString);
}
private abstract void WriteEventToLog(string DisplayString);
}
Now, I am assuming that, since your static method didn't actually DO
anything with the string, that you will want to do many things with the
string, depending on what your code is up to. In that case, each of those
many things would require you to create a class like so:
public class MyTracer : IExceptionClass
{
private override void WriteEventToLog(string DisplayString)
{
// -- code goes here to write the event to a trace log.
}
}
public class MyEventLogger : IExceptionClass
{
private override void WriteEventToLog(string DisplayString)
{
// -- code goes here to write the event to the event log
}
}
and so on.
Add in a method in our handy-dandy class factory:
public class MyClassFactory : IMyAbstractFactory
{
/// ... singleton declaration and Instance property
/// ... other factory methods
public IExceptionClass GetEventLogger()
{
return new MyEventLogger();
}
}
In your code, when an event occurs, you would do this:
// snippet
// note: In this example, I will use a singleton to control the creation
of the class factory
try {
// offending, but not offensive, code
} catch (Exception ex) // for the sake of simplicity
{
MyEventLogger el = MyClassFactory.Instance.GetEventLogger();
el.LogThisEvent(ex);
}
You are no longer calling a static method. On the other hand, you do not
have to define the code more than once. The code is part of the handling of
errors. It is cohesively correct to place it in the inheritance tree for
the handling of errors.
Interestingly enough, the way this ends up being implemented... it's a
strategy pattern after all.
Alas, a good idea is hard to kill.
--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik
Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
- Next message: CK: "Re: Threading question"
- Previous message: CK: "Threading question"
- In reply to: Dan Bass: "Re: MVP's: static methods in interfaces. (REDEFINED)"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|