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

Posted

技术标签:

【中文标题】以下代码中的 CommaDelimLog 类是不是违反单一职责原则?【英文标题】:Does the class CommaDelimLog in the following code violates single responsibility principle?以下代码中的 CommaDelimLog 类是否违反单一职责原则? 【发布时间】:2012-10-12 04:51:30 【问题描述】:

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

日志文件 A

logType1, 10/1/2012, 12, abc logType2,a,b,c,d,2012 年 11 月 1 日 logType1,2012 年 10 月 2 日,21,定义 logType2,e,f,c,d,2012 年 12 月 1 日 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】:

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

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

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

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

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

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

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

【讨论】:

你能详细说明“由于从 LogFile 继承的行为”吗? GetParsedFieldString in LogFile 是类的逻辑所在,但它不是抽象的,所以我假设 some 继承者之间共享一些基本实现。这可能导致将来需要修改基类中此方法的行为。开放/封闭原则是关于将您的类设计为对扩展开放,但对修改封闭,因此根据该原则,不应在基类中实现可能发生变化的规则。

以上是关于以下代码中的 CommaDelimLog 类是不是违反单一职责原则?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Swift中的UIWebView中加载URL?

如何检测类中是不是存在特定的成员变量?

junit测试

从向量而不是数组调用类函数

QUBIC 双聚类学习以及代码编写运行

Clang 是不是正确拒绝仅通过特化定义类模板的嵌套类的代码?