3

我目前正在努力理解我应该如何组织/构建我已经创建的类。该类执行以下操作:

  1. 作为构造函数中的输入,它需要一组日志
  2. 在构造函数中,它通过一系列实现我的业务逻辑的算法来验证和过滤日志
  3. 在完成所有过滤和验证后,它会返回有效和过滤日志的集合(列表),这些日志可以在 UI 中以图形方式呈现给用户。

这是一些描述我正在做的事情的简化代码:

class FilteredCollection
{
  public FilteredCollection( SpecialArray<MyLog> myLog)
  {   
  // validate inputs
  // filter and validate logs in collection
  // in end, FilteredLogs is ready for access
  }
  Public List<MyLog> FilteredLogs{ get; private set;}

}

但是,为了访问此集合,我必须执行以下操作:

var filteredCollection = new FilteredCollection( specialArrayInput );
//Example of accessing data
filteredCollection.FilteredLogs[5].MyLogData;

其他关键输入:

  1. 我预见应用程序中只存在这些过滤集合中的一个(因此我应该将其设为静态类吗?或者可能是单例?)
  2. 创建对象的可测试性和灵活性很重要(也许因此我应该将其保留为可测试的实例类?)
  3. 如果可能的话,我宁愿简化日志的取消引用,因为实际的变量名称很长,并且需要大约 60-80 个字符才能获取实际数据。
  4. 我试图保持这个类简单是这个类的唯一目的是创建这个经过验证的数据集合。

我知道这里可能没有“完美”的解决方案,但我真的很想通过这种设计来提高我的技能,我非常感谢这样做的建议。提前致谢。


编辑:

感谢所有回答者,Dynami Le-Savard 和 Heinzi 都确定了我最终使用的方法 - 扩展方法。我最终创建了一个 MyLogsFilter 静态类

namespace MyNamespace.BusinessLogic.Filtering
{
    public static class MyLogsFilter
    {
        public static IList<MyLog> Filter(this SpecialArray<MyLog> array)
        {
            // filter and validate logs in collection
            // in end, return filtered logs, as an enumerable
        }
    }
}

我可以通过这样做在代码中创建一个只读集合

IList<MyLog> filteredLogs = specialArrayInput.Filter(); 
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
4

4 回答 4

3

听起来您对日志做了三件事:

  1. 验证它们
  2. 过滤它们并
  3. 访问它们

您希望将日志存储在集合中。标准的 List 集合非常适合,因为它不关心其中的内容,为您提供 LINQ 并允许您使用只读包装器锁定集合

我建议您将您的担忧分为上述三个步骤。

考虑

interface ILog
{
  MarkAsValid(bool isValid);
  ... whatever data you need to access...
}

将您的验证逻辑放在一个单独的接口类中

interface ILogValidator
{
  Validate(ILog);
}

还有你的过滤逻辑

interface ILogFilter
{
  Accept(ILog);
}

然后使用 LINQ,类似于:

List<MyLog> myLogs = GetInitialListOfLogsFromSomeExternalSystem();
myLogs.ForEach(x => MyLogValidator(x));
List<MyLog> myFilteredLogs = myLogs.Where(x => MyLogFilter(x));

关注点分离使测试和可维护性变得更好。并远离单身人士。由于包括可测试性在内的许多原因,它们不受欢迎。

于 2010-05-25T23:43:50.273 回答
1

一些想法:

  • 正如您正确指出的那样,使用实例化类可以提高可测试性。

  • 如果 (A) 在整个系统中只有一个类的实例,并且(B) 您需要在应用程序的多个不同位置访问此实例,而无需传递对象,则应该使用单例。应避免不必要地使用单例模式(或任何其他类型的“全局状态”),因此除非您的情况也满足 (B),否则我不会在这里使用单例。

  • 对于简单的取消引用,请考虑使用indexer。这将允许您编写:

    FilteredCollection 过滤日志 = new FilteredCollection( secialArrayInput );
    //访问数据示例
    过滤日志[5].MyLogData;
  • 如果您的类仅包含构造函数和访问结果的字段,则使用简单方法可能比使用更合适。如果您想以奇特的方式进行操作,可以将其编写为 的扩展方法SpecialArray<MyLog>允许您像这样访问它:
    List<MyLog> 过滤日志 = secialArrayInput.Filter();
    //访问数据示例
    过滤日志[5].MyLogData;
于 2010-05-25T23:41:50.403 回答
1

在我看来,您正在查看一个返回过滤日志集合的方法,而不是包装您的业务逻辑的集合类。像这样:

class SpecialArray<T>
{
     [...]

     public IEnumerable<T> Filter()
     {   
         // validate inputs
         // filter and validate logs in collection
         // in end, return filtered logs, as an enumerable
     }

     [...]
}

但是,看起来您真正希望的实际上是将负责过滤日志的业务逻辑从SpecialArray类中分离出来,可能是因为您觉得该逻辑涉及许多并不真正关心的事情SpecialArray,或者因为Filter不适用于所有的一般情况SpecialArray

在这种情况下,我的建议是将您的业务逻辑隔离在另一个中namespace,也许是一个使用和/或需要其他组件以应用所述业务逻辑的组件,并将您的功能作为扩展方法提供,具体来说:

namespace MyNamespace.Collections
{
    public class SpecialArray<T>
    {
        // Shenanigans
    }
}

namespace MyNamespace.BusinessLogic.Filtering
{
    public static class SpecialArrayExtensions
    {
        public static IEnumerable<T> Filter<T>(this SpecialArray<T> array)
        {
            // validate inputs
            // filter and validate logs in collection
            // in end, return filtered logs, as an enumerable
        }
    }
}

当您需要使用该业务逻辑时,它看起来像这样:

using MyNamespace.Collections; // to use SpecialArray
using MyNamespace.BusinessLogic.Filtering; // to use custom log filtering business logic
namespace MyNamespace
{
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main2()
        {
            SpecialArray<Logs> logs;
            var filteredLogs = logs.Filter();
        }
    }
}
于 2010-05-26T01:26:32.697 回答
0

如果您想为最终过滤数组继承 SpecialArray 的接口,则从具有实例成员的 SpecialArray 派生。这将允许:
filteredCollecction[5].MyLogData; ETC..

于 2010-05-25T23:45:58.600 回答