Frage

Ich bin zu kämpfen zur Zeit zu verstehen, wie ich sollte eine Klasse organisieren / Struktur, die ich bereits erstellt haben. Die Klasse führt Folgendes aus:

  1. Wie der Eingang in den Konstruktor, dauert es eine Sammlung von Protokollen
  2. Im Konstruktor es überprüft und filtert die Protokolle durch eine Reihe von Algorithmen Umsetzung meiner Business-Logik
  3. Nachdem alle Filterung und Validierung abgeschlossen ist, es gibt eine Auflistung (eine Liste) der gültigen und gefilterte Protokolle, die grafisch in einer Benutzeroberfläche den Benutzer präsentiert werden können.

Hier ist etwas vereinfachte Code zu beschreiben, was ich tue:

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;}

}

Um jedoch diese Sammlung zugreifen zu können, muss ich die folgenden Schritte ausführen:

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

Weitere wichtige Stücke von Eingabe:

  1. Ich sehe nur eine dieser gefilterten Sammlungen in der Anwendung vorhandenen (deshalb sollte ich es machen eine statische Klasse? Oder vielleicht ein Singleton?)
  2. Testbarkeit und Flexibilität bei der Erstellung des Objekts wichtig ist (vielleicht deshalb soll ich für Testbarkeit dies eine instanzierte Klasse halten?)
  3. Ich würde es vorziehen, die dereferenzierenden der Protokolle zu vereinfachen, wenn überhaupt möglich, da die tatsächlichen Variablennamen sind ziemlich lang und es dauert einige 60-80 Zeichen nur auf die tatsächlichen Daten.
  4. Mein Versuch, diese Klasse einfach zu halten ist, dass der einzige Zweck der Klasse ist diese Sammlung von validierten Daten zu erstellen.

Ich weiß, dass es möglicherweise keine „perfekte“ Lösung hier, aber ich versuche wirklich meine Fähigkeiten mit diesem Entwurf zu verbessern, und ich würde Ratschläge sehr zu schätzen, das zu tun. Danke im Voraus.


EDIT:

Danke an alle Antworter, beide Dynami Le-Savard und Heinzi identifiziert den Ansatz, den ich am Ende mit - Erweiterungsmethoden. Ich landete eine MyLogsFilter statische Klasse zu schaffen

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
        }
    }
}

und ich kann eine einzige Sammlung dieser in Code erstellen zu lesen, indem Sie

IList<MyLog> filteredLogs = specialArrayInput.Filter(); 
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
War es hilfreich?

Lösung

The way I see it, you are looking at a method that returns a collection of filtered log, rather than a collection class wrapping your business logic. Like so:

class SpecialArray<T>
{
     [...]

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

     [...]
}

However, it does look like what you really wish is actually to separate the business logic in charge of filtering the logs from the SpecialArray class, perhaps because you feel like the logic touches many things that do not really concern SpecialArray, or because Filter does not apply to all generic cases of SpecialArray.

In that case my suggestion would be to isolate your business logic in another namespace, perhaps one that uses and/or requires other components in order to apply said business logic, and offer your functionality as an extension method, concretly :

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
        }
    }
}

And when you need to use that business logic, it would look like this :

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();
        }
    }
}

Andere Tipps

It sounds like you do three things to your logs:

  1. Validate them
  2. Filter them and
  3. Access them

You want to store the logs in a collection. The standard List collection is a good fit since it doesn't care what's in it, gives you LINQ and allows you to lock the collection with a read-only wrapper

I would suggest you separate your concerns into the three steps above.

Consider

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

Put your validation logic in a separate interface class

interface ILogValidator
{
  Validate(ILog);
}

And your filtering logic in yet another

interface ILogFilter
{
  Accept(ILog);
}

Then with LINQ, something like:

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

The separation of concerns makes testing and maintainability much better. And stay away from the singletons. For many reasons including testability they are out of favor.

Some thoughts:

  • As you correctly point out, using an instanced class improves testability.

  • Singletons should be used if (A) there is only one instance of the class in your whole system and (B) you need to access this instance at multiple different places of your application without having to pass the object around. Unnecessary use of the Singleton pattern (or any other kind of "global state") should be avoided, so unless (B) is satisfied in your case as well, I'd not use a singleton here.

  • For simple dereferencing, consider using an indexer. This will allow you to write:

    FilteredCollection filteredlogs = new FilteredCollection( secialArrayInput );
    //Example of accessing data
    filteredlogs[5].MyLogData;
  • If your class only consists of a constructor and a field to access the result, using a simple method might be more appropriate than using a class. If you want to do it the fancy way, you could write it as an extension method for SpecialArray<MyLog>, allowing you to access it like this:
    List<MyLog> filteredlogs = secialArrayInput.Filter();
    //Example of accessing data
    filteredlogs[5].MyLogData;

If you want to inherit the interface of SpecialArray for you final filtered array then derive from SpecialArray instad of having an instance member. That would allow:
filteredCollecction[5].MyLogData; etc..

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top