2 votes

Comment utiliser un modèle de spécification pour mes besoins ?

J'ai lu quelques exemples du modèle de spécification, mais il est difficile d'avoir une idée de la manière de mettre en œuvre ce modèle.

Je suis en train de développer un énorme programme pour un client. J'ai besoin d'importer des fichiers XML d'une banque spécifique, puis d'effectuer une validation pour chaque fichier. Les codes de grand livre ont différentes méthodes (subs, bo, rcc). Ainsi, lorsqu'un fichier indique SUBS, il doit être envoyé à une méthode SUBS.

Exemple ici :

Interfaces :

  • BlackBank
  • BlueBank
  • RedBank

Codes de grand livre :

  • SUBS
  • BO
  • RCC

Résultat :

  • BlackBank a des SUBS, BO et RCC.
  • BlueBank a des filiales
  • RedBank a BO et RCC

Pouvez-vous me donner un exemple de code ou m'indiquer la direction à suivre ?

10voto

T I Points 5828

Sans contexte, il est difficile de répondre à cette question. Je vais donc essayer d'inventer quelque chose à partir des informations dont je dispose et j'espère que cela vous donnera une idée.

Créez une interface de spécification simple comme suit

interface ISpecification<T>
{
    IsSatisfiedBy(T obj);
}

Supposons que vous disposiez d'une interface de base pour les "banques" ressemblant à ceci

interface IBank
{
    LedgerCode LedgerCode { get; set; }
}

Et un enum de LedgerCodes

[Flags]
enum LedgerCodes
{
    SUBS, BO, RCC
} 

Vous pouvez créer une simple spécification de code de livre pour vérifier les LedgerCodes d'une IBank (ceci est assez général, vous devez le rendre spécifique à vos besoins).

class LedgerCodeSpec : ISpecification<IBank>
{
    private LedgerCode code;

    public LedgerCodeSpecification(LedgerCode code)
    {
        this.code = code
    }

    public override bool IsSatisfiedBy(IBank obj)
    {
        return obj.LedgerCode == code;
    }
}

Le cas échéant, vous pouvez utiliser votre spécification, ici je l'utilise pour fournir une validation simple. Une autre utilisation est la "sélection", par exemple pour obtenir des données d'un référentiel.

class Bank : IBank
{
    private ISpecification<IBank> spec;
    private LedgerCode code;

    public Bank(ISepcification<IBank> spec)
    {
        this.code = code;
        this.spec = spec;
    }

    public LedgerCode LedgerCode { get; set; }

    public bool IsValid 
    { 
        get
        {
            return spec.IsSatisfiedBy(this);
        }
    } 
}

Et enfin un peu de code pour tester/démontrer rapidement ce qui précède.

class Main
{
    public static void Main()
    {
        var spec = new LedgerCodeSpec(LedgerCodes.SUB)
        var blueBank = new Bank(spec);

        Console.WriteLine(blueBank.IsValid); // false

        blueBank.LedgerCode = LedgerCodes.RCC | LedgerCodes.SUB;

        Console.WriteLine(blueBank.IsValid); // false

        blueBank.LedgerCode = LedgerCodes.SUB;

        Console.WriteLine(blueBank.IsValid); // true
    }
}

Il existe de bons exemples sur le web qui permettent d'ajouter des méthodes d'extension et de remplacer des opérateurs pour obtenir une spécification succincte et, à mon avis, plus facile à lire.

class MessageSpecification : Specification<string>
{
    public const int MIN_LENGTH = 5;
    public const int MAX_LENGTH = 60;

    public override bool IsSatisfiedBy(string s)
    {
        Specification<string> length = new LengthSpecification(MIN_LENGTH, MAX_LENGTH);
        Specification<string> isNull = new IsNullSpecification<string>();

        Specification<string> spec = length && !isNull;

        return spec.IsSatisfiedBy(s);
    }
}

La façon dont j'utilise actuellement le modèle est probablement excessive, mais j'aime l'idée de supprimer, de réutiliser et, d'une manière générale, de rendre la logique plus OO.

Edit : après avoir lu certains des commentaires, votre problème semble être plus lié à un problème général de répartition plutôt qu'au modèle de spécification. étant donné vos interfaces, vous pourriez plus simplement faire.

class BankFacade
{
    public Send(IBlueBank bank)
    {
        // validate with specification
        // do stuff with IBlueBank
    }

    public Send(IRedBank bank)
    {
        // validate with specification
        // do stuff with IRedBank
    }

    //...
}

en réfléchissant un peu plus, vous pourriez faire quelque chose du genre

class Parser
{
    static class RedBankSpecification : ISpecification<XElement>
    {
        public override bool IsSatisfiedBy(XElement element)
        {
            return element.Value.equals("RED");
        }
    }

    public void Parse(XDocument doc)
    {
        var rspec = new RedBankSpecification();

        foreach(XElement e in doc)
        {
            if (r.IsSatisfiedBy(e))
            {
                IRedBank bank = new RedBank(e);
                bankFacade.Send(bank);
            }
        }

        //...
    }
}

Cependant, il se peut que vous n'ayez pas vraiment besoin du modèle et que vous ne deviez pas essayer d'y intégrer le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X