52 votes

Comment une couche de service s'intègre-t-elle dans la mise en œuvre de mon référentiel?

J'ai créé un POCO de la classe du modèle et un référentiel de la classe qui gère la persistance. Depuis le POCO ne peut pas accéder au dépôt, il y a beaucoup de logique métier tâches dans le référentiel qui ne semble pas juste. De ce que j'ai lu, il semble que j'ai besoin d'un service à la couche qui se trouve entre l'INTERFACE utilisateur des consommateurs et le dépôt de la couche. Ce que je ne suis pas sûr, c'est exactement la façon dont il est censé fonctionner...

En plus de la couche de service, il devrait également être une entreprise distincte de la couche logique, ou est-ce le rôle de la couche de service?

Devrait-il y avoir un seul service par référentiel?

Est la couche de service, le seul moyen que l'INTERFACE utilisateur peut exemple, le modèle d'objets ou de ne le référentiel de fournir à la nouvelle instance du modèle pour le service?

Dois-je mettre mon paramètre, le modèle et d'autres validations dans la couche de service que de faire des choses comme la vérification pour s'assurer une entrée est valide et qu'un élément à mettre à jour dans la base de données avant la mise à jour?

Pouvez le modèle référentiel de l'INTERFACE et de tous de faire des appels à la couche de service, ou est-ce juste pour l'INTERFACE utilisateur de consommer?

Est la couche de service censé être toutes les méthodes statiques?

Ce serait une manière typique pour appeler le service à la couche de l'INTERFACE utilisateur?

Ce validations doivent être sur le modèle vs la couche de service?

Voici un exemple de code pour mes couches existantes:

public class GiftCertificateModel
{
    public int GiftCerticiateId {get;set;}
    public string Code {get;set;}
    public decimal Amount {get;set;}
    public DateTime ExpirationDate {get;set;}

    public bool IsValidCode(){}
}


public class GiftCertificateRepository
{
    //only way to access database
    public GiftCertificateModel GetById(int GiftCertificateId) { }
    public List<GiftCertificateModel> GetMany() { }
    public void Save(GiftCertificateModel gc) { }
    public string GetNewUniqueCode() { //code has to be checked in db }

    public GiftCertificateModel CreateNew()
    {
        GiftCertificateModel gc = new GiftCertificateModel();
        gc.Code = GetNewUniqueCode();
        return gc;
    }              
}

Mise à JOUR: Je suis actuellement en utilisant des formulaires web et classique ADO.NET. J'ai l'espoir de passer à la MVC et EF4 finalement.

Mise à JOUR: merci à @Lester pour sa grande explication. Je comprends maintenant que j'ai besoin d'ajouter une couche de service pour chacun de mes dépôts. Cette couche sera le SEUL moyen de l'INTERFACE utilisateur ou d'autres services peuvent communiquer avec le dépôt et contient toutes les validations qui ne tiennent pas dans le domaine de l'objet (par exemple, - les validations qui ont besoin d'appeler le repo)

public class GiftCertificateService()
{

    public void Redeem(string code, decimal amount)
    {
        GiftCertificate gc = new GiftCertificate();
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        if (amount <= 0 || GetRemainingBalance(code) < amount)
        {
            throw new ArgumentException("Invalid amount");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.Redeem(code, amount);
    }

    public decimal GetRemainingBalance(string code)
    {
        GiftCertificate gc = new GiftCertificate();            
        if (!gc.IsValidCode(code))
        {
            throw new ArgumentException("Invalid code");
        }

        GiftCertificateRepository gcRepo = new GiftCertificateRepository();
        gcRepo.GetRemainingBalance(code);
    }

    public SaveNewGC(GiftCertificate gc)
    {
        //validates the gc and calls the repo save method
        //updates the objects new db ID
    }

}

Questions

  1. Dois-je ajouter le même (et peut-être plus) des propriétés pour le service que j'ai sur mon modèle (montant, code, etc) ou dois-je seulement offrir des méthodes qui acceptent GiftCertificate objets et directe des paramètres?

  2. Dois-je créer une instance par défaut de la GiftCertificate entité lorsque le Service constructeur est appelé ou tout simplement en créer de nouveaux selon les besoins (par exemple pour la validation de méthodes dans le service que besoin d'appeler les méthodes de validation dans l'entité? Aussi, la même question au sujet de la création d'un référentiel par défaut de l'instance...?

  3. Je sais que je exposer les fonctionnalités de l'opération par l'intermédiaire du service, dois-je également exposer les méthodes de l'entité (par exemple - IsValidCode, etc)?

  4. C'est ok pour l'INTERFACE utilisateur de créer simplement un nouveau GiftCertificate objet directement sans passer par le service (par exemple - pour appeler le paramètre de validation des méthodes de l'entité). Si pas, comment les faire respecter?

  5. Sur la couche d'INTERFACE utilisateur, lorsque je veux créer un nouveau certificat-cadeau, dois-je appeler le modèle/service des validations (comme IsValidExpirationDate, etc) directement à partir de la couche d'INTERFACE utilisateur OU dois-je l'hydrate de l'objet, puis de le transmettre à valider, et ensuite de retour à une sorte de récapitulatif de la validation du retour à l'INTERFACE utilisateur?

Aussi, si je veux Racheter de la couche d'INTERFACE utilisateur, dois-je d'abord appeler le modèle/service de validation des méthodes de l'INTERFACE utilisateur pour donner de la rétroaction d'utilisateur, puis d'appeler la Racheter la méthode qui sera exécutée de la même vérifie une fois encore à l'interne?

Exemple pour l'appel de service à faire Racheter opération à partir de l'INTERFACE utilisateur:

string redeemCode = RedeemCodeTextBox.Text;

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate(); //do this to call validation methods (should be through service somehow?)

if (!gc.IsValid(redeemCode))
{
    //give error back to user
}

if (gcService.GetRemainingBalance(redeemCode) < amount)
{
    //give error back to user
}

//if no errors
gcService.Redeem(code,amount);

Exemple de création d'un nouveau certificat-Cadeau à partir de l'INTERFACE utilisateur:

GiftCertificateService gcService = new GiftCertificateService();
GiftCertificate gc = new GiftCertificate();

if (!gc.IsValidExpDate(inputExpDate))
{
    //give error to user..
}

//if no errors...
gc.Code = gcService.GetNewCode();
gc.Amount = 10M;
gc.ExpirationDate = inputExpDate;
gcService.SaveNewGC(gc);
//method updates the gc with the new id...

Quelque chose sent mauvais sujet de manière GCs sont créés et comment les validations sont séparés entre l'entité/service. L'utilisateur/consommateur ne doit pas être concerné par ce que les validations sont dans la place... des conseils?

43voto

Lester Points 2537

Jetez un oeil à S#arp Architeture . C'est comme une des meilleures pratiques cadre architectural pour la construction de ASP.NET les applications MVC. L'architecture générale pattern est d'avoir 1 dépôt par l'entité qui est responsable uniquement pour l'accès aux données et 1 service par référentiel, qui n'est responsable que pour la logique métier et la communication entre les contrôleurs et les services.

Pour répondre à vos questions sur la base S#arp Architeture:

En plus de la couche de service, il devrait également être une entreprise distincte de la couche logique, ou est-ce le rôle de la couche de service?

Les modèles devraient être responsables de la validation au niveau des champs (ex. l'aide nécessaire attributs de champ), tandis que les contrôleurs de valider les données avant de les enregistrer (ex. vérification de l'état avant l'enregistrement).

Devrait-il y avoir une couche de service par le référentiel?

Oui - il devrait y avoir un service par le référentiel (pas 1 couche de service par le référentiel, mais je suppose que vous vouliez dire).

Est la couche de service, le seul moyen que l'INTERFACE utilisateur peut exemple, le modèle d'objets ou de ne le référentiel de fournir à la nouvelle instance du modèle pour le service?

Les référentiels et les services peuvent retourner une seule entité, une collection d'entités ou objets de transfert de données (Otd). Contrôleurs de transmettre ces valeurs à un constructeur statique méthode dans le modèle qui sera de retour une instance du modèle.

ex en Utilisant les Dto:

GiftCertificateModel.CreateGiftCertificate(int GiftCerticiateId, string Code, decimal Amount, DateTime ExpirationDate)

Dois-je mettre mon paramètre, le modèle et d'autres validations dans la couche de service que de faire des choses comme la vérification pour s'assurer une entrée est valide et qu'un élément à mettre à jour dans la base de données avant la mise à jour?

Les modèles de valider les valeurs de niveau ex. s'assurant d'entrée est valide en vérifiant les champs requis, l'âge ou la date de plages, etc. Les Services doivent faire une validation nécessaire que requiert la vérification en dehors de la valeur de modèle ex. Vérifier que le certificat-cadeau n'a pas été rachetés encore, vérifier des propriétés de la boutique le certificat-cadeau est pour).

Pouvez le modèle référentiel de l'INTERFACE et de tous de faire des appels à la couche de service, ou est-ce juste pour l'INTERFACE utilisateur de consommer?

Contrôleurs et autres services devraient être les seuls à faire des appels à la couche de service. Les Services devraient être le seul fait d'émettre des appels vers des dépôts.

Est la couche de service censé être toutes les méthodes statiques?

Ils peuvent être, mais il est plus facile de maintenir et d'étendre, si ils ne le sont pas. Change d'entités et de l'ajout ou de la suppression des sous-classes sont plus facile à modifier si il y a 1 service par entité / sous-classe.

Ce serait une manière typique pour appeler le service à la couche de l'INTERFACE utilisateur?

Quelques exemples de contrôleurs de l'appel de la couche de service:

giftCertificateService.GetEntity(giftCertificateId); (which in turn is just a call to the giftCertificateRepository.GetEntity(giftCertificateId)

giftCertificateService.Redeem(giftCertificate);

Ce validations doivent être sur le modèle vs la couche de service?

Déjà répondu ci-dessus.

Mise à JOUR

Puisque vous êtes à l'aide de Formulaires web, il peut être un peu plus difficile à comprendre quelques-uns des concepts, mais de tout ce que j'ai mentionné est applicable depuis que je suis décrivant générale paradigme MVC. ADO.NET pour l'accès aux données n'a pas d'importance puisque l'accès aux données est découplée par les référentiels.

Dois-je ajouter le même (et peut-être plus) des propriétés pour le service que j'ai sur mon modèle (montant, code, etc) ou dois-je seulement offrir des méthodes qui acceptent GiftCertificate objets et directe des paramètres?

Vous avez besoin de regarder les services que exactement ce que leur nom l'indique - les actions que les contrôleurs peuvent invoquer. Vous n'aurez pas besoin de propriétés qui sont définies dans le modèle car ils sont déjà disponibles dans le modèle.

Dois-je créer une instance par défaut de la GiftCertificate entité lorsque le Service constructeur est appelé ou tout simplement en créer de nouveaux selon les besoins (par exemple pour la validation de méthodes dans le service que besoin d'appeler les méthodes de validation dans l'entité? Aussi, la même question au sujet de la création d'un référentiel par défaut de l'instance...?

Les contrôleurs et les services devraient avoir des champs privés pour des services et des dépôts, respectivement. Vous ne devriez pas être instancier pour chaque action / méthode.

Je sais que je exposer les fonctionnalités de l'opération par l'intermédiaire du service, dois-je également exposer les méthodes de l'entité (par exemple - IsValidCode, etc)?

Pas trop sûr de ce que vous voulez dire ici. Si les services de retour entités ensuite ces méthodes sur les entités sont déjà exposés. Si ils reviennent Otd alors cela implique que vous êtes intéressé seulement à certaines informations.

Pour la validation, je peux voir pourquoi vous êtes un peu inquiet car il n'y a validation effectuée directement sur le modèle et d'autres types de validation dans les services. La règle que j'ai utilisé, c'est que si la validation requiert des appels à la db, alors il devrait être fait dans la couche de service.

C'est ok pour l'INTERFACE utilisateur de créer simplement un nouveau GiftCertificate objet directement sans passer par le service (par exemple - pour appeler le paramètre de validation des méthodes de l'entité). Si pas, comment les faire respecter?

Sur la couche d'INTERFACE utilisateur, lorsque je veux créer un nouveau certificat-cadeau, dois-je appeler le modèle/service des validations (comme IsValidExpirationDate, etc) directement à partir de la couche d'INTERFACE utilisateur OU dois-je l'hydrate de l'objet, puis de le transmettre à valider, et ensuite de retour à une sorte de récapitulatif de la validation du retour à l'INTERFACE utilisateur?

Pour ces 2 questions permet de passer au travers d'un scénario:

L'utilisateur saisit les informations pour créer un nouveau certificat et la soumet. Il y a au niveau du champ de la validation de sorte que si une zone de texte est null ou si le montant est négatif, il déclenche une erreur de validation. En supposant que tous les champs sont valides le contrôleur peut appeler le service d' gcService.Save(gc).

Le service vérifiez la logique métier, comme si le magasin a déjà émis trop de certificats-cadeaux. Elle renvoie soit un enum pour l'état si il y a plusieurs codes d'erreur ou lève une exception avec l'information d'erreur.

Enfin, les appels de service en gcRepository.Save(gc).

3voto

alliswell Points 3064
  1. Vous n'avez pas à créer un référentiel par entité,voir ici pour plus d',

    Habituellement, on définit un référentiel par globale dans le domaine. Qui est: nous ne pas disposer d'un référentiel par entité! Si nous avons un regard sur un simple ordre d'entrée le système de l'entité, Afin peut-être de la racine d'un Ordre total. Ainsi, nous va avoir un Ordre de Dépôt.

  2. Devrait-il y avoir un seul service par référentiel? -> Pas toujours, comme vous l'avez peut utiliser plusieurs référentiels dans un seul service.

  3. Le Service crée l'instance du Modèle référentiel de ne jamais intervenir pour Modèle, en fait il retourne l'Entité qui modèle utilisera par la suite.

  4. Poignée d'Entrée/plage etc type de validation au niveau de l'INTERFACE utilisateur(u pouvez utiliser javascript ou toute autre bibliothèque), et laissez-les Services de ne traiter que les affaires de l'entreprise. Vous pouvez obtenir les avantages des Attributs qui n'est pas le même.

  5. UI->Service->Dépôt, si le dépôt est d'appeler le service client de thr doit être quelque chose de mal, de l'OMI.


Vous les changements de code,

  1. Faire Modèle et Référentiels distincts.

    public class GiftCertificateModel
    {
    }
    public class GiftCertificateRepository
    {
       //Remove Model related code from here, and just put ONLY database specific code here, (no business logic also). Common methods would be Get, GetById, Insert, Update etc. 
    
        Since essence of Repository is to have common CRUD logic at one place soyou don't have to write entity specific code. 
        You will create entity specific repository in rare cases, also by deriving base repository.
    
    }
    
    public class GiftCertificateService()
    {
        //Create Model instance here
        // Use repository to fill the model (Mapper)
    
    }
    

0voto

Nikos Baxevanis Points 4511

Vous pouvez créer un service appelé GiftCertificateService.

De cette façon, vous permettra de coordonner toutes les tâches qui n'appartient pas à la responsabilité de l'GiftCertificateModel en service. (À ne pas confondre avec un service WCF).

Le service de contrôle de toutes les tâches de sorte que votre INTERFACE utilisateur (ou de ce que l'appelant que peut-être) utiliser les méthodes définies dans le service.

Le service sera alors appeler des méthodes sur le modèle, utiliser le référentiel, créer des opérations, etc.

Pour ex. (basé sur l'exemple de code que vous avez fournie):

public class GiftCertificateService 
{
   public void CreateCertificate() 
   {
      //Do whatever needs to create a certificate.
      GiftCertificateRepository gcRepo = new GiftCertificateRepository();
      GiftCertificateModel gc = gcRepo.CreateNew();
      gc.Amount = 10.00M;
      gc.ExpirationDate = DateTime.Today.AddMonths(12);
      gc.Notes = "Test GC";
      gcRepo.Save(gc);
   }
}

L'INTERFACE utilisateur fera appel à la CreateCertificate méthode (arguments de passage, etc) et la méthode peut retourner quelque chose aussi.

REMARQUE: Si vous souhaitez que la classe à la loi sur l'INTERFACE utilisateur si ensuite créer une classe contrôleur (si vous faites MVC) ou un présentateur de la classe (si vous faites MVVM, et ne pas vouloir tout mettre à l'intérieur du ViewModel) et l'utilisation de la GiftCertificateService à partir de cette classe.

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