Je m'excuse d'avance mais ce sera une longue question.Question de conception - comment briser la dépendance entre les classes en utilisant une interface?
Je suis bloqué. J'essaie d'apprendre les tests unitaires, C#, et les modèles de conception - tout à la fois. (C'est peut-être mon problème.) En tant que tel, je suis en train de lire l'Art of Unit Testing (Osherove), et Clean Code (Martin), et Head First Design Patterns (O'Reilly). Je commence à peine à comprendre les délégués et les événements (que vous verriez si vous étiez à la traîne de mes questions récentes). Je ne comprends toujours pas les lambdas.
Pour contextualiser tout cela, je me suis donné un projet d'apprentissage que j'appelle goAlarms. J'ai une classe d'alarme avec des membres auxquels vous vous attendez (NextAlarmTime, Name, AlarmGroup, Event Trigger, etc.)
Je voulais que le "Timer" de l'alarme soit extensible, j'ai donc créé une interface IAlarmScheduler comme suit ...
public interface AlarmScheduler
{
Dictionary<string,Alarm> AlarmList { get; }
void Startup();
void Shutdown();
void AddTrigger(string triggerName, string groupName, Alarm alarm);
void RemoveTrigger(string triggerName);
void PauseTrigger(string triggerName);
void ResumeTrigger(string triggerName);
void PauseTriggerGroup(string groupName);
void ResumeTriggerGroup(string groupName);
void SetSnoozeTrigger(string triggerName, int duration);
void SetNextOccurrence (string triggerName, DateTime nextOccurrence);
}
Cette interface IAlarmScheduler définit un composant qui déclenche une alarme (déclenchement) qui se propagera jusqu'au ma classe d'alarme et augmenter le déclenchement de l'événement de l'alarme lui-même. C'est essentiellement le composant "Timer".
J'ai trouvé que le composant Quartz.net est parfaitement adapté pour cela, j'ai donc créé une classe QuartzAlarmScheduler qui implémente IAlarmScheduler.
Tout ce qui va bien. Mon problème est que la classe d'alarme est abstraite et je veux créer beaucoup de différents types d'alarme. Par exemple, j'ai déjà une alarme Heartbeat (déclenchée tous les (int) intervalles de minutes), AppointmentAlarm (déclenchée sur la date et l'heure définies), Alarme quotidienne (déclenchée tous les jours à X) et peut-être d'autres.
Et Quartz.NET est parfaitement adapté pour gérer cela.
Mon problème est un problème de conception. Je veux être capable d'instancier une alarme de n'importe quelle sorte sans que ma classe d'alarme (ou aucune classe dérivée) ne sache quoi que ce soit à propos de Quartz. Le problème est que Quartz a des usines impressionnantes qui retournent juste la bonne configuration pour les déclencheurs qui seront nécessaires par mes classes d'alarme. Ainsi, par exemple, je peux obtenir un déclencheur de Quartz en utilisant TriggerUtils.MakeMinutelyTrigger pour créer un déclencheur pour l'alarme de battement de coeur décrite ci-dessus. Ou TriggerUtils.MakeDailyTrigger pour l'alarme quotidienne. Je suppose que je pourrais résumer de cette façon. Indirectement ou directement, je veux que mes classes d'alarmes puissent consommer les classes TriggerUtils.Make * sans rien savoir d'elles. Je sais que c'est une contradiction, mais c'est pourquoi je pose la question. Je pensais mettre un champ de délégué dans l'alarme qui serait assignée à l'une de ces méthodes de Make mais en faisant cela je crée une dépendance dure entre l'alarme et le quartz que je veux éviter à la fois pour des buts d'essai d'unité et de conception . J'ai pensé utiliser un switch pour le type dans QuartzAlarmScheduler par here mais je sais que c'est un mauvais design et j'essaie d'apprendre un bon design.
Vous êtes géniaux et merci d'avance pour vos réponses.
Seth