以下代码中的CommaDelimLog类是否违反单一责任原则?

时间:2012-10-12 04:51:30

标签: c# .net solid-principles single-responsibility-principle open-closed-principle

程序解析日志文件 - 每个日志文件可能有不同类型的字段格式(固定宽度,逗号分隔等)。此外,每个日志文件都混合了几种不同类型的日志 - 每种日志都有不同的字段定义。例如,CSV日志文件可能类似于

日志文件A

logType1, 10/1/2012, 12, abc
logType2, a, b, c, d, 11/1/2012
logType1, 10/2/2012, 21, def
logType2, e, f, c, d, 12/1/2012
logType3, 3.23, ....

以下是代码。以下代码中违反了多少固体原则?一个人说布局定义列表不应该与解析日志混在一起。所以它至少违反了SRP(或更多)?重构结构的最佳方法是什么?

// Field
public interface IField { .... }
public class Field : IField { ... common field methods, etc.... }
public class FixedWidthField : Field { }
public class CommaDelimField : Field { ... }

// Log type
public interface ILogType<out T> where T : IField { ... IEnumerable<T> Fields { get; } }
public class LogType<T> : ILogType<T> where T : IField 
{ .... 
    public LogType(..., List<T> fields) { ... Fields = fields; }
}

// File
public inteface ILogFile<out T> where T: IField { ... IEnumerable<ILogType<T>> LogTypeList { get; set; } }
public abstract class LogFile<T> : ILogFile<T> where T: IField 
{ ....
    public IEnumerable<ILogType<T>> LogTypeList { get; set; }
    public virtual string Row { get { ... } set { ...} }
    public string GetParsedFieldString() { ... }
}
public class CommaDelimLog : LogFile<CommaDelimField>
{
     public override string Row { get { ... } set { ...code to parse the line...} }
     public override string GetParsedFieldString() { ... }
}

// The following initilize code store all the layout information
public static List<ILogFile<IField>> LogFileList = new List<ILogFile<IField>>
{
    new CommaDelimLog("logFileA", ...., new List<ILogType<CommaDelimField>> {
        new LogType<CommaDelimField>("logType1", ... new List<CommaDelimField>{ .... }
        new LogType<CommaDelimField>("logType2", ... new List<CommaDelimField>{ .... }
        ....
    }),
    new CommaDelimLog("logFileB", .... a long long list

主程序根据文件名模式从LogFileList获取项目,逐行读取日志文件并分配属性Row,然后获取解析后的字符串。

1 个答案:

答案 0 :(得分:1)

由于LogFile对行为的继承,它可能违反了开放封闭原则(尽管GetParsedFieldString在抽象基础中实际上不是虚拟的,如果没有更多的上下文,很难确定。)

您可以使用某种解析器接口,这些接口可以实现几个具体的类,只要您需要一个新的接口,就可以构建一个新的接口。 LogFile类的风险在于你将创建更多的子类型,然后开始查找共享行为,然后重构为几个级别的继承,如果不进行大量测试就无法进行任何更改,这将变得一团糟。 / p>

您似乎主要询问基于问题标记的开放原则,但依赖性反转原则也被违反,因为您的具体类直接依赖于其他具体类,例如依赖于CommaDelimField的CommaDelimLog。 / p>

例如,使用ninject,您可以执行以下操作:

Bind<IField>().To<CommaDelimField>().WhenInjectedInto<CommaDelimLog>(); 

然后通过其构造函数将具体字段传递到日志中。不同类型的字段具有相同的签名,因此CommaDelimLog类定义不需要直接知道它依赖于CommaDelimField。

可能还有其他违规行为,但我会推迟其他人。