1

I have a set of types that can be customized by formatters. A formatter is a function object defined as Func<string, string, string>. Client of a library may than choose to implement FormattedLoggerBase with one of formatters provided or write new one.

public abstract class FormattedLoggerBase : LoggerBase
    {
        public Func<string, string, string> Formatter { get; set; }    

        /.../
    }

Where is a best place to put all the function objects?

  • One static class?
  • Wrapper classes implementing IFormatter?
  • Factory?

Static class has least overhead, but wrapper classes would provide a clear message to the users, that formatter can be injected. On the other hand, they provide much code overherad, as well as factory. Which one would you choose and why? Or maybe you have better solution?

  • When in doubt, use the simplest solution which satisfies the requirements. A static class seem like a fine place to collect these formatters. – JacquesB Feb 18 '18 at 14:10
3

This is really just dealer's choice (barring company coding standards or a dev lead who has decided how to approach it, at which point the question becomes a bit moot).


I like static classes the most, as using nested static classes allows you to essentially use "namespace folders". I don't know if there's a proper name for this, that's what I call it (and I'm loosely translating from Dutch).

For example:

public static class Formatters
{
    public static class Date
    {
        public static Func<DateTime, string> UtcFormat = ...;
        public static Func<DateTime, string> IsoFormat = ...;
    }

    public static class PhoneNumber
    {
        public static Func<string, string> InternationalFormat = ...;
        public static Func<string, string> NationalFormat = ...;
        public static Func<string, string> InternalFormat = ...;
    }
}

Note: I removed the second string parameter, as I suspect the subdivision in the example already selects the formatting that your second parameter was likely going to be used for.

This gives you a nice autocomplete functionality on your intellisense, which I very much appreciate if there is a large amount of formatters.

I've also used similar approaches for e.g. global config settings. I like having the ability to sort a large list of options with minimal impact on the code base (nested classes don't really dirty the rest of your code base).

0

There are a lot of similar uses of static classes out there for default implementations. something like:

myLogger.Formatter = LoggerNamespace.DefaultFormatters.UkDate;

would not be unusual.

Personally my view is when you have interfaces and typed delegates why not use them?

public interface IFormatter
{
    string Format(string in, string format);
}

or

public delegate string Formatter(string in, string format);

If you have a class or function which implements one of these then its containing, namespace class or project is less important, as its use is clearly indicated from the type.

The bad side of a static would be if it was referenced directly somewhere

myLogger.WriteLog(string msg)
{
     //now i cant test :(
     this.write(LoggerNamespace.DefaultFormatters.UkDate(msg,""));
}

While you can avoid this by being careful you cant prevent it happening in other peoples code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.