2012-10-12 23 views
0

程序解析日志文件 - 每个日志文件可能有不同类型的字段格式(固定宽度,逗号分隔等)。另外每个日志文件都混合了几种不同类型的日志 - 每种日志文件都有不同的字段定义)。例如,CSV日志文件可能看起来像以下代码中的类CommaDelimLog是否违反单一责任原则?

日志文件

 
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根据文件名模式得到一个项目,逐行读取日志文件线和分配财产然后拿到解析字符串。

回答

1

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

您可以改为使用某种类型的解析器接口,其中几个具体的类实现,并且每当您需要一个新类时,就可以创建一个新类。 LogFile类的风险在于你将创建更多的子类型,然后开始寻找共享行为,然后重构成几个级别的继承,并且它将变得一团糟,无需做任何测试就无法更改任何内容。

您似乎主要是基于问题的标签询问开放关闭原则,但依赖倒置原则也被违反,因为您的具体类直接依赖于其他具体类,例如依赖于CommaDelimField的CommaDelimLog。

随着ninject,例如,你可以这样做:

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

,然后具体的领域通入日志,通过它的构造。不同类型的字段具有相同的签名,因此CommaDelimLog类定义不需要直接知道它依赖于CommaDelimField。

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

+0

你能否详细说明“由于LogFile对行为的继承性”? – ca9163d9

+0

LogFile中的GetParsedFieldString是类的逻辑驻留的地方,但它不是抽象的,所以我假设有一些基础实现可以在* some * inheritors之间共享。这可能会导致将来需要修改基类中此方法的行为。开放/封闭的原则是关于设计你的类可以扩展,但是不能修改,所以根据原则,可能改变的规则不应该在基类中实现。 – David

相关问题