0

プログラムはログ ファイルを解析します。各ログ ファイルは、異なる種類のフィールド形式 (固定幅、カンマ区切りなど) を持つ場合があります。また、各ログ ファイルにはいくつかの異なる種類のログが混在しています (種類ごとに異なるフィールド定義があります)。たとえば、CSV ログ ファイルは次のようになります。

ログファイル A

logType1、2012 年 10 月 1 日、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 から項目を取得し、ログ ファイルを 1 行ずつ読み取り、プロパティを割り当て、Row解析された文字列を取得します。

4

1 に答える 1

1

これはおそらく、LogFile からの動作の継承により、open-closed の原則に違反しています (ただし、GetParsedFieldString は実際には抽象ベースでは仮想ではなく、さらにコンテキストがないと特定するのは困難です)。

代わりに、いくつかの具体的なクラスを実装するある種のパーサー インターフェースを用意し、新しいものが必要なときはいつでも新しいものを構築することができます。LogFile クラスのリスクは、より多くのサブタイプを作成し、共有動作を見つけ始め、いくつかのレベルの継承にリファクタリングすることであり、大量のテストを行わなければ何も変更できないという混乱になります。

質問のタグに基づいて、主に開閉原則について質問しているようですが、具象クラスが CommaDelimField に依存する CommaDelimLog のように、他の具象クラスに直接依存しているという点で依存性反転の原則にも違反しています。

たとえば、ninject を使用すると、次のようなことができます。

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

次に、コンストラクターを介して具体的なフィールドをログに渡します。さまざまなタイプのフィールドが同じシグネチャを持っているため、CommaDelimLog クラス定義は、CommaDelimField に依存していることを直接知る必要はありません。

他にも違反があるかもしれませんが、他に譲ります。

于 2012-10-12T05:11:46.980 に答える