2010-01-25 6 views
1

J'ai une entité, équivalente à une tâche, qui peut avoir plusieurs états. La "tâche" peut être dans un état en attente, transmis ou en échec. Chacun de ces états aura également des données uniques. Par exemple, dans un état défaillant, l'entité doit avoir une raison pour l'échec, dans l'état en attente, elle doit avoir une date limite pour l'évaluation, etc.Comment modéliser un entitly avec plusieurs états?

Alors que ce qui précède me conduit à penser que je devrais avoir un objet séparé pour représenter chaque état, l'identifiant sous-jacent pour l'entité devrait rester le même, me repoussant vers la pensée de ceci comme un seul objet.

De plus, la transition d'un état à l'autre nécessite une certaine logique. Une tâche "en attente" passant à un état "passé" sera traitée différemment d'une tâche "ayant échoué" effectuant la même transition.

Si les représentations pour chaque état étaient exactement les mêmes, j'utiliserais simplement une propriété primitive et j'en ferais avec. Cependant, puisque les différents états ont des représentations légèrement différentes, j'ai eu du mal à trouver la meilleure façon de modéliser cela. La logique pour gouverner l'état interne devient un peu en désordre alors je me suis dit que je prendrais du recul et reconsidérerais. Des pensées?

J'utilise C# bien que je considère cette langue agnostique.

Répondre

1

Lorsque j'ai lu cette question pour la première fois, ma réponse consistait à utiliser une énumération pour définir l'état. Après relue, cependant, je suggère une des façons suivantes:

  1. Mettre en oeuvre chaque tâche en tant que classe séparée (PendingTask, PassedTask, ...) avec le même parent, et un constructeur qui accepte une tâche de tout type qui vient avant cet état.
  2. Implémentez une tâche et créez une nouvelle classe TaskStateData avec des classes enfant pour les données nécessaires à chaque état.
  3. Mettre en œuvre une tâche, mais une méthode distincte pour changer l'état pour chaque type d'état avec des paramètres pour les attributs supplémentaires nécessaires à cet état

Je propose ces solutions pour assurer l'intégrité des données.

0

Jetez un oeil à la state pattern.

+0

Je connais ce modèle. De ma compréhension, et de la façon dont je l'ai utilisé, il est très utile de changer le comportement d'un objet à l'exécution. Avec ce problème, je pense, il s'agit plus de gérer les différences dans la représentation de l'objet. Il se peut que j'aboie le mauvais arbre en général ici. Juste expliquer le problème m'a aidé à identifier quelques objectifs incompatibles. –

0

Cela ressemble à une application idéale de l'héritage de l'objet et le polymorphisme.

abstract class Task 
{ 
     public int TaskId { get; private set; } 
     abstract PassedTask TransitionToPassed(); 
     ... 
} 

class PendingTask : Task 
{ 
     PassedTask TransitionToPassed() 
     { 
      PassedTask passed = new PassedTask(); 
      passed.TaskId = TaskId; 
      ... 
      return passed; 
     } 
     ... 
} 

class PassedTask : Task 
{ 
     PassedTask TransitionToPassed() 
     { 
      return this; 
     } 
     ... 
} 

class FailedTask : Task 
{ 
     public string ReasonForFailure { get; private set; } 
     PassedTask TransitionToPassed() 
     { 
      ... 
     } 
     ... 

} 
1

Aller avec une approche purement orientée objet a des inconvénients. À moins que vous n'ayez l'intention de faire beaucoup de gestion de code polymorphe, évitez de représenter directement l'état de votre classe de domaine en utilisant le polymorphisme. J'ai choisi une approche plus hybride. Les différents états doivent être modélisés en tant qu'arborescence d'héritage parent/enfant séparée. Commencez avec une classe de base abstraite MyState qui a pour enfants MyState1, MyState2 et MyState3. (Voir Jeffrey's answer pour un exemple

L'entité qui a besoin de son état suivi a un attribut de 'état actuel' qui est de type MyState Quand l'entité change d'état c'est une simple affectation ou un appel de setter() pour changer Vous pouvez construire des instances singleton de chaque état si vous le souhaitez, ou construire de nouvelles instances pour chaque changement d'état.Cela dépend de la fréquence à laquelle l'état change et combien d'objets ont leur état suivi.Si les chiffres deviennent trop grands, vous pouvez envisager l'approche singleton

1

La "tâche" peut être dans un état en attente, réussi ou en échec. Une tâche "en attente" passant à un état "passé" sera traitée différemment d'une tâche "ayant échoué" effectuant la même transition.

Cela semble une collection plutôt étrange d'états. Je m'attendais à ce qu'une tâche prenne un certain temps à s'exécuter, donc la transition de l'attente à l'exécution réussit ou échoue, et les tâches qui ne s'exécutent pas avant la fin de leur temps expirent. S'il y a aussi une transition d'échoué à échoué-et-expiré, cela pourrait ajouter un autre état. Dessinez une machine d'état pour trouver les états.

Premièrement, avez-vous besoin de modéliser les états structurellement? Est-ce qu'un drapeau en attente/expiré, une heure planifiée et un résultat le font (avec l'échec et le succès comme les deux sous-types de résultat)? De quoi les clients de la tâche ont-ils besoin?

Deuxièmement, êtes-vous en interaction avec une tâche ou un planificateur? Il n'est pas rare de donner une description de tâche à un planificateur et de récupérer un futur, qui peut être interrogé sur le résultat de la tâche. Mais la tâche elle-même n'est pas exposée, seulement si elle est complète et le résultat. Si vous avez besoin de progression, vous pouvez avoir un ordonnanceur qui peut être interrogé par ID de tâche pour obtenir la progression, plutôt qu'un objet de tâche auquel vous tenez une référence. Avoir un objet de tâche qui change d'état rend difficile l'obtention d'un ensemble cohérent des données d'état de celui-ci, jusqu'à ce qu'il atteigne un état final. Si l'état 'passé' n'a pas d'information d'échec, interroger 'êtes-vous échoué', suivi par 'obtenir le statut d'échec' mène facilement à une course à moins que vous n'érigiez le verrouillage (ewww), rendant ainsi atomiquement un objet souhaitable, temps pendant lequel votre objet de tâche devient plus ou moins équivalent à l'ID transmis à un planificateur.

Questions connexes