Question

Je suis actuellement en difficulté à comprendre comment j'organiser / structurer une classe que je l'ai déjà créé. La classe effectue les opérations suivantes:

  1. Comme son entrée dans le constructeur, il faut une collection de journaux
  2. Dans le constructeur, il valide et filtre les journaux à travers une série d'algorithmes mettre en œuvre ma logique métier
  3. Après tout filtrage et de validation est terminée, elle retourne une collection (une liste) des journaux valides et filtrés qui peuvent être présentées à l'utilisateur dans une interface utilisateur graphique.

Voici un code simplifié décrit ce que je fais:

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

}

Cependant, pour avoir accès à cette collection, je dois faire ce qui suit:

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

D'autres éléments clés de l'entrée:

  1. je prévois une seule de ces collections filtrées existantes dans l'application (donc devrais-je faire une classe statique? Ou peut-être un singleton?)
  2. testabilité et la flexibilité dans la création de l'objet est important (donc peut-être que je devrais garder cette une classe instanciée pour testabilité?)
  3. Je préfère simplifier le déréférencement des journaux si possible, que les noms de variables réelles sont assez longues et il faut des personnages 60-80 pour obtenir juste les données réelles.
  4. Ma tentative de garder ce simple de classe est que le seul but de la classe est de créer cette collection de données validées.

Je sais qu'il peut y avoir aucune solution « parfaite », mais je suis vraiment essayer d'améliorer mes compétences avec cette conception et j'apprécierait des conseils pour le faire. Merci d'avance.


EDIT:

Merci à tous les answerers, les deux Dynami Le-Savard et Heinzi a identifié l'approche que je fini par utiliser - Méthodes extension. J'ai fini par créer une classe statique 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
        }
    }
}

et je peux créer une lecture seule collection de ce dans le code en faisant

IList<MyLog> filteredLogs = specialArrayInput.Filter(); 
ReadOnlyCollection<MyLog> readOnlyFilteredLogs = new ReadOnlyCollection<MyLog>(filteredLogs);
Était-ce utile?

La solution

La façon dont je le vois, vous êtes à la recherche d'une méthode qui retourne une collection de journal filtrée plutôt que d'une classe de collection enveloppant votre logique métier. Comme ceci:

class SpecialArray<T>
{
     [...]

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

     [...]
}

Cependant, il ressemble ce que vous avez vraiment souhait est en fait de séparer la logique métier en charge de filtrer les journaux de la classe SpecialArray, peut-être parce que vous vous sentez comme la logique touche beaucoup de choses qui ne SpecialArray vraiment pas de problème, ou parce que Filter ne s'applique pas à tous les cas génériques de SpecialArray.

Dans ce cas, ma suggestion serait d'isoler votre logique métier dans un autre namespace, peut-être celui qui utilise et / ou nécessite d'autres composants afin d'appliquer ladite logique métier et offrir vos fonctionnalités comme une méthode d'extension, concrètement:

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

Et quand vous avez besoin d'utiliser cette logique métier, il ressemblerait à ceci:

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

Autres conseils

On dirait que vous faites trois choses à vos journaux:

  1. Valider les
  2. Filtre les et
  3. les accès

Vous voulez stocker les journaux dans une collection. La collection de liste standard est un bon ajustement, car il ne se soucie pas ce qui est en elle, vous donne LINQ et vous permet de verrouiller la collection avec une lecture seule enveloppe

Je vous suggère de séparer vos préoccupations dans les trois étapes ci-dessus.

Considérons

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

Mettez votre logique de validation dans une classe d'interface séparée

interface ILogValidator
{
  Validate(ILog);
}

Et votre logique de filtrage dans un autre

interface ILogFilter
{
  Accept(ILog);
}

Alors avec LINQ, quelque chose comme:

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

La séparation des préoccupations rend les tests et la maintenabilité beaucoup mieux. Et rester à l'écart des singletons. Pour de nombreuses raisons, y compris testabilité ils sont hors de faveur.

Quelques réflexions:

  • Comme vous l'avez à juste titre, en utilisant une classe instanciée améliore la testabilité.

  • singletons doit être utilisé si (A) il n'y a qu'une seule instance de la classe dans votre système entier et (B), vous devez accéder à cette instance à plusieurs endroits différents de votre application sans avoir à passer autour de l'objet. L'utilisation inutile du motif Singleton (ou tout autre type de « état global ») devrait être évitée, donc à moins que (B) est satisfaite dans votre cas aussi, je ne serais pas utiliser un singleton ici.

  • Pour déréférencement simple, pensez à utiliser un indexeur . Cela vous permettra d'écrire:

    FilteredCollection filteredlogs = new FilteredCollection( secialArrayInput );
    //Example of accessing data
    filteredlogs[5].MyLogData;
  • Si votre classe ne se compose que d'un constructeur et un champ pour accéder au résultat, à l'aide d'un simple méthode est peut-être plus approprié que d'utiliser un class . Si vous voulez faire le chemin de fantaisie, vous pouvez l'écrire comme méthode d'extension SpecialArray<MyLog>, vous permettant d'y accéder comme ceci:
    List<MyLog> filteredlogs = secialArrayInput.Filter();
    //Example of accessing data
    filteredlogs[5].MyLogData;

Si vous voulez hériter l'interface de SpecialArray pour vous tirer tableau finale Filtré alors de SpecialArray instad d'avoir un membre de l'instance. Cela permettrait:
    filteredCollecction [5] .MyLogData; etc ..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top